Bash-Variable Sichtbarkeit in der Unterschale der Befehlsersetzung

7

Ich lese ein Linux-Shell-Skriptbuch und habe die folgende Warnung gefunden:

"Durch die Befehlssubstitution wird eine sogenannte Subshell zum Ausführen des eingeschlossenen Befehls erstellt. Eine Subshell ist eine separate untergeordnete Shell, die von der Shell generiert wird, in der das Skript ausgeführt wird. Aus diesem Grund stehen dem Subshell-Befehl keine Variablen zur Verfügung, die Sie im Skript erstellen."

Ich habe versucht, eine Variable in der CLI meiner aktuellen Bash-Shell zu erstellen und dann die Subshell einzugeben, um zu überprüfen, ob ich sie auf dem Bildschirm drucken kann. Also ja, ich kann es nicht tun, scheint dem obigen Zitat zu entsprechen. Ich habe jedoch das folgende Skript mit Befehlsersetzung ausgeführt:

#!/bin/bash
var=5.5555
ans=$(echo $var)
echo $ans

Und das Ergebnis ist:

5.5555

Wie ich verstanden habe, sollte der Wert von var nicht gedruckt werden, da die Subshell nicht in der Lage sein sollte, ihn zu "sehen". Warum passiert das?

Donatas
quelle
Aber der Kommentar im Buch sagt, dass es so ist. Ich habe sogar die Variable $ BASH_SUBSHELL zum Ausdrucken in die Befehlssubstitution aufgenommen und 1 ausgegeben, was bedeutet, dass eine Unterschale erstellt wurde.
Donatas
3
Dein Buch ist nicht sehr gut.
Michael Homer
1
Zumindest ist diese Aussage unklar und irreführend, und ansonsten ist sie einfach völlig falsch, wie Sie in dieser Frage gezeigt haben.
Michael Homer
1
Wohltätig muss ich raten, dass das Buch bedeutet, dass "nicht für die Zuweisung verfügbar sind " (mit dem Gedanken, dass die "Variable" nicht verfügbar ist), aber es ist eine sehr wenig hilfreiche Art, dies zu sagen, wenn es wirklich das ist, was sie bedeuteten.
Michael Homer
1
Lesen Sie einige unserer Fragen zu sushell , z. B. unix.stackexchange.com/questions/157957/… und unix.stackexchange.com/questions/138463/…
Gilles '

Antworten:

10

Die Aussage:

Aus diesem Grund stehen dem Befehl subshell keine Variablen zur Verfügung, die Sie im Skript erstellen.

ist falsch. Der Bereich einer in der übergeordneten Shell definierten Variablen ist das gesamte Skript (einschließlich der mit Befehlsersetzung erstellten Subshells).

Laufen:

#!/bin/bash
var=5.5555
ans1=$(echo $var)
ans2=$(var=6; echo $var)
echo $ans1
echo $ans2

wird das Ergebnis geben:

5.5555
6

$var wird durch die Unterschale aufgelöst:

  • Wenn keine lokale Variable angegeben ist, wird der Wert von drei globalen Variablen verwendet
  • Wenn eine lokale Variable angegeben wird, verwendet sie ihren Wert

Siehe auch das Beispiel 21-2 .

Techraf
quelle
10

Die angegebene Aussage ist nicht wahr. Es ist auch nicht wahr, dass die Variable vor dem Ausführen der Subshell vorab ersetzt wurde.

Sie können dies direkt mithilfe der variablen Indirektion überprüfen :

$ x=hello
$ echo Result is $(y=x ; echo ${!y} ; echo world)
Result is hello world

Die Variable xist definitiv direkt für die Subshell verfügbar (anstatt ihren Wert zuvor erweitert zu haben), da sie ${!y}von der Variablen liest, in der der Name gespeichert ist y- die zum Zeitpunkt der Erstellung der Subshell nicht vorhanden war.


Eine gemeinnützige Lektüre der Passage aus dem Buch wäre, dass die "Variable" nicht verfügbar ist, weil Sie ihren Wert nicht dauerhaft ändern können. Alle Variablenzuweisungen, die Sie innerhalb einer Subshell vornehmen, stehen der übergeordneten Shell anschließend nicht mehr zur Verfügung, unabhängig davon, ob neue Variablen (wie y) erstellt oder vorhandenen Variablen Ersatzwerte zugewiesen werden . Wenn die Unterschale zugewiesen wird, xhat der neue Wert Auswirkungen auf die Unterschale, aber das anschließende Lesen ergibt den ursprünglichen Wert:

$ x=world
$ echo $(x=hello ; echo $x)
hello
$ echo $x
world

Es ist keine sehr klare Art, dies auszudrücken, zumindest in der von Ihnen zitierten Passage. Wenn das ganze Buch so ist, können Sie möglicherweise ein besseres finden (oder stattdessen hier Fragen lesen).

Michael Homer
quelle