Wie werden Umgebungsvariablen gedruckt / wiedergegeben?

74

Wie drucke ich die gerade festgelegte Umgebungsvariable?

NAME=sam echo "$NAME" # empty

Sie können hier sehen, wie evales funktioniert. Ist dies der Weg?

NAME=sam eval 'echo $NAME' # => sam
ThomasReggi
quelle
2
NAME=sam echo whateverändert den Wert von NAMEin der Shell nicht.
Rici

Antworten:

80

Diese müssen als unterschiedliche Befehle ausgeführt werden, z.

NAME=sam; echo "$NAME"
NAME=sam && echo "$NAME"

Die Erweiterung $NAMEauf leere Zeichenfolge wird von der Shell vor dem Ausführen früher durchgeführt. Wenn echodie NAMEVariable an die echoUmgebung des Befehls übergeben wird, erfolgt die Erweiterung bereits (auf Nullzeichenfolge).

So erzielen Sie das gleiche Ergebnis mit einem Befehl:

NAME=sam printenv NAME
heemayl
quelle
Ich habe eine Notiz über hinzugefügt printenv. Hoffe es ist OK, @heemayl
Aaron McDaid
2
Beachten Sie, dass nur der printenvBefehl -based die Semantik des OP-Befehls beibehält : Definieren NAMEals 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 NAMEals eine Nur-die-aktuelle-Shell-Exit-Shell-Variable , die alle nachfolgenden Shell- Befehle sehen, aber keine externen Dienstprogramme .
mklement0
13

Um die vorhandenen Antworten mit einer wichtigen Klarstellung zusammenzuführen:

Wie bereits erwähnt, besteht das Problem NAME=sam echo "$NAME"darin, dass $NAMEdie aktuelle Shell sie erweitert, bevor die Zuweisung NAME=samwirksam 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:

  • als Umgebungsvariable
  • Dies ist nur für den aufgerufenen Befehl definiert .

Mit anderen Worten: NAMENur für den aufgerufenen Befehl vorhanden und hat keine Auswirkung auf die aktuelle Shell (wenn zuvor keine Variable mit dem Namen NAMEvorhanden war, gibt es danach keine; eine bereits vorhandene NAMEVariable 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:

  • eine Schale VariableNAME (nur) als eine Umgebungsvariable
    • Wenn echoein Befehl auf Umgebungsvariablen basieren würde NAME, würde er nicht definiert (oder möglicherweise anders als zuvor definiert).
  • das lebt nach dem Befehl weiter.

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 exportoder markiert declare -x).


[1] Technisch gesehen bashverstößt POSIX hier (wie es ist zsh): Da evaleine spezielle Shell integriert ist, sollte die vorhergehende NAME=samZuweisung dazu führen, dass die Variable $NAMEnach Abschluss des Befehls im Gültigkeitsbereich bleibt, aber das passiert nicht.
Wenn Sie jedoch bashim POSIX-Kompatibilitätsmodus ausgeführt werden, ist dieser kompatibel.
dashund kshsind 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 evalnur bei der Eingabe Sie vollständig kontrollieren oder implizit vertrauen .

mklement0
quelle
4

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.

Ljm Dullaart
quelle
4

Dies funktioniert auch mit dem Semikolon.

NAME=sam; echo $NAME

ThomasReggi
quelle