Ihre erste Vermutung war richtig, aber Sie haben ein schlechtes Beispiel verwendet.
Wenn die Shell den Befehl liest
foo=bar echo $foo
das erste, was es tut (oder zumindest eines der ersten Dinge)
ist nach Variablenreferenzen zu suchen (wie $foo
) und bewerten sie. Dann es verarbeitet, was von der Linie übrig ist.
(Dies kann ein bisschen zu stark vereinfacht werden;
sehen bash(1)
oder der Bash-Referenzhandbuch für Details.)
Sie haben also den Befehl
echo (nichts)
mit laufen foo=bar
; aber es ist zu spät; Es gibt nichts mehr zu sehen auf den Wert von $foo
.
Sie können dies mit der folgenden Sequenz demonstrieren:
$ foo=oldvalue
$ foo=bar echo "$foo"
oldvalue
Aber
foo=bar Befehl
ist der Weg zu gehen. Einige Beispiele, die funktionieren, sind:
foo=bar sh -c 'echo "$foo"'
und
foo=bar env
(Möglicherweise möchten Sie das durchleiten grep foo
.)
Ich habe gerade den Satz bemerkt, den Sie zitiert haben,
"Wenn diese Zuweisungsanweisungen einem in die Shell integrierten Befehl vorangehen, z. B. ...",
schlägt vor, dass integrierte Befehle (wie z echo
) einen Sonderfall darstellen.
Es ist (für mich zumindest) intuitiv, dass Sie nach diesem "Befehlsbereich" suchen
müsste funktionieren, indem Sie in einem untergeordneten Prozess eine Umgebungsvariable setzen,
und es ist nicht klar, wie es für einen integrierten Befehl funktionieren würde, der nicht in einem untergeordneten Prozess ausgeführt wird.
Nicht viele integrierte Befehle greifen direkt auf die Umgebung zu.
und ihre Interaktion mit Shell-Variablen ist manchmal unecht.
Ich habe aber noch ein paar Beispiele gefunden, nach denen Sie vielleicht mehr suchen:
foo=bar eval 'echo $foo'
wird "bar" anzeigen, da die Bewertung von $foo
wird verschoben.
Es wird von der behandelt eval
(eingebauter) Befehl anstelle des anfänglichen Parsing-Durchlaufs der Shell.
Oder erstellen Sie eine Textdatei (zum Beispiel) showme.sh
.
Setzen Sie ein echo $foo
(oder echo "$foo"
) Befehl hinein und sagen
foo=bar . showme.sh
Das ist wahrscheinlich, worüber Ihr Buch spricht, wenn es sagt:
“… Die Shell muss die korrekte Reihenfolge verfolgen, in der Variablenreferenzen aufgelöst werden…”
Irgendwie führt die Shell die Befehle aus showme.sh
mit foo
gleich bar
.
und kehrt dann zum vorherigen Wert von zurück foo
(wenn überhaupt)
wenn es zu seinem primären Eingang (dem Terminal) zurückkehrt.
$foo
wird "erweitert", bevor noch etwas passiert. Ich habe meine Antwort mit weiteren Gedanken zu integrierten Befehlen aktualisiert.echo '$foo'
gibt den String aus$foo
.cat '$foo'
undls -l '$foo’
Suchen Sie nach einer Datei namens$foo
.grep '$foo' .bashrc
sucht nach der Zeichenfolge$foo
in deiner.bashrc
Datei. Aber die Shell behandelt, im Gegensatz zu den anderen Programmen, etwas$
speziell;sh -c '$foo'
sucht nach einer Umgebungsvariablen namensfoo
. Zum Beispiel,foo=date sh -c '$foo'
wird ein laufen lassendate
Befehl. (Vergleiche mit der Tatsache, dasscat '\0107'
undls -l '\0107’
Suchen Sie nach einer Datei namens\0107
, undgrep '\0107'
sucht nach der Zeichenfolge\0107
, aberecho -e '\0107'
gibt den String ausG
,… (Fortsetzung)echo
Leckereien\
besonders wenn der-e
Option ist vorgesehen.)Das Problem ist hier die variable Erweiterung (
$foo
→ value) geschieht vor der Auswertung des gesamten Befehls (putfoo=bar
in die Umwelt laufenecho ...
).Es würde für Befehle funktionieren, die selbst auf die Umgebung zugreifen:
Bash hat nicht wirklich den richtigen Spielraum für das, was Sie suchen. Sie müssen den "Subprozess" -Trick verwenden, um einen neuen zu erhalten verarbeiten für den Befehl. (Natürlich bedeutet das nur Lesezugriff, Nein Änderungen erreichen das übergeordnete Element ...) Use
( ... )
So erstellen Sie eine Subshell:quelle