Wie drucke ich die gerade festgelegte Umgebungsvariable?
NAME=sam echo "$NAME" # empty
Sie können hier sehen, wie eval
es funktioniert. Ist dies der Weg?
NAME=sam eval 'echo $NAME' # => sam
Wie drucke ich die gerade festgelegte Umgebungsvariable?
NAME=sam echo "$NAME" # empty
Sie können hier sehen, wie eval
es funktioniert. Ist dies der Weg?
NAME=sam eval 'echo $NAME' # => sam
Antworten:
Diese müssen als unterschiedliche Befehle ausgeführt werden, z.
NAME=sam; echo "$NAME"
NAME=sam && echo "$NAME"
Die Erweiterung $NAME
auf leere Zeichenfolge wird von der Shell vor dem Ausführen früher durchgeführt. Wenn echo
die NAME
Variable an die echo
Umgebung des Befehls übergeben wird, erfolgt die Erweiterung bereits (auf Nullzeichenfolge).
So erzielen Sie das gleiche Ergebnis mit einem Befehl:
NAME=sam printenv NAME
printenv
. Hoffe es ist OK, @heemayl
printenv
Befehl -based die Semantik des OP-Befehls beibehält : Definieren NAME
als Umgebungsvariable mit Befehlsbereich , die nur der aufgerufene Befehl und seine untergeordneten Prozesse sehen, aber keine nachfolgenden Shell-Befehle. Die anderen Befehle machen etwas ganz anderes: Sie definieren sich NAME
als eine Nur-die-aktuelle-Shell-Exit-Shell-Variable , die alle nachfolgenden Shell- Befehle sehen, aber keine externen Dienstprogramme .
Um die vorhandenen Antworten mit einer wichtigen Klarstellung zusammenzuführen:
Wie bereits erwähnt, besteht das Problem NAME=sam echo "$NAME"
darin, dass $NAME
die aktuelle Shell sie erweitert, bevor die Zuweisung NAME=sam
wirksam wird.
Lösungen, die die ursprüngliche Semantik (des (ineffektiven) Lösungsversuchs NAME=sam echo "$NAME"
) beibehalten :
Verwenden Sie entweder eval
[1]
(wie in der Frage selbst) oder printenv
(wie von Aaron McDaid zu Heemayls Antwort hinzugefügt ) oder bash -c
(aus Ljm Dullaarts Antwort ) in absteigender Reihenfolge der Effizienz:
NAME=sam eval 'echo "$NAME"' # use `eval` only if you fully control the command string
NAME=sam printenv NAME
NAME=sam bash -c 'echo "$NAME"'
printenv
ist kein POSIX-Dienstprogramm, aber es ist sowohl unter Linux als auch unter macOS / BSD verfügbar.
Mit diesem Aufrufstil ( <var>=<name> cmd ...
) wird Folgendes definiert NAME
:
Mit anderen Worten: NAME
Nur für den aufgerufenen Befehl vorhanden und hat keine Auswirkung auf die aktuelle Shell (wenn zuvor keine Variable mit dem Namen NAME
vorhanden war, gibt es danach keine; eine bereits vorhandene NAME
Variable bleibt unverändert).
POSIX definiert die Regeln für diese Art von Aufruf in seinem Kapitel Befehlssuche und -ausführung .
Die folgenden Lösungen funktionieren sehr unterschiedlich (von Heemayls Antwort ):
NAME=sam; echo "$NAME"
NAME=sam && echo "$NAME"
Während sie dieselbe Ausgabe erzeugen , definieren sie stattdessen:
NAME
(nur) als eine Umgebungsvariable
echo
ein Befehl auf Umgebungsvariablen basieren würde NAME
, würde er nicht definiert (oder möglicherweise anders als zuvor definiert).Beachten Sie, dass jede Umgebungsvariable auch als Shell-Variable verfügbar gemacht wird, aber das Gegenteil ist nicht der Fall: Shell-Variablen sind nur für die aktuelle Shell und ihre Subshells sichtbar, nicht jedoch für untergeordnete Prozesse wie externe Dienstprogramme und (nicht bezogene) Skripte (es sei denn, sie sind als Umgebungsvariablen mit export
oder markiert declare -x
).
[1] Technisch gesehen bash
verstößt POSIX hier (wie es ist zsh
): Da eval
eine spezielle Shell integriert ist, sollte die vorhergehende NAME=sam
Zuweisung dazu führen, dass die Variable $NAME
nach Abschluss des Befehls im Gültigkeitsbereich bleibt, aber das passiert nicht.
Wenn Sie jedoch bash
im POSIX-Kompatibilitätsmodus ausgeführt werden, ist dieser kompatibel.
dash
und ksh
sind immer konform.
Die genauen Regeln sind kompliziert und einige Aspekte müssen von den Implementierungen entschieden werden. Siehe auch Befehlssuche und -ausführung .
Außerdem gilt die übliche Haftungsausschluss: Verwenden Sie eval
nur bei der Eingabe Sie vollständig kontrollieren oder implizit vertrauen .
Die Syntax
variable=value command
wird häufig verwendet, um Umgebungsvariablen für einen bestimmten Prozess festzulegen. Sie müssen jedoch verstehen, welcher Prozess welche Variable erhält und wer sie interpretiert. Als Beispiel mit zwei Muscheln:
a=5
# variable expansion by the current shell:
a=3 bash -c "echo $a"
# variable expansion by the second shell:
a=3 bash -c 'echo $a'
Das Ergebnis ist 5 für das erste Echo und 3 für das zweite.
Dies funktioniert auch mit dem Semikolon.
NAME=sam; echo $NAME
NAME=sam echo whatever
ändert den Wert vonNAME
in der Shell nicht.