Wenn ich renne
export TEST=foo
echo $TEST
Es gibt foo aus.
Wenn ich renne
TEST=foo echo $TEST
Es tut nicht. Wie kann ich diese Funktionalität erhalten, ohne Export oder ein Skript zu verwenden?
Wenn ich renne
export TEST=foo
echo $TEST
Es gibt foo aus.
Wenn ich renne
TEST=foo echo $TEST
Es tut nicht. Wie kann ich diese Funktionalität erhalten, ohne Export oder ein Skript zu verwenden?
Antworten:
Dies liegt daran, dass die Shell die Variable in der Befehlszeile erweitert, bevor sie den Befehl ausführt, und die Variable zu diesem Zeitpunkt nicht vorhanden ist. Wenn du benutzt
TEST=foo; echo $TEST
es wird klappen.
export
wird die Variable in der Umgebung von später ausgeführten Befehlen erscheinen lassen (wie dies in Bash funktioniert, siehe help export
). Wenn die Variable nur in der Umgebung eines Befehls angezeigt werden soll, verwenden Sie das, was Sie versucht haben:
TEST=foo your-application
$TEST
bevor die Befehlszeile ausgeführt wird. Sobald das ausgeführt echo
wird (beachten Sie auch, dass dies echo
normalerweise in den integrierten Shell-Befehl und nicht in übersetzt wird /bin/echo
), wird die in der Umgebung festgelegte Variable angezeigt. Weist echo $TEST
jedoch nicht echo
an, den Inhalt einer Variablen TEST
aus ihrer Umgebung auszugeben . Es weist die Shell an, echo
mit Argument zu arbeiten, das dem entspricht, was sich aktuell in der aufgerufenen Variablen befindet TEST
- und das sind zwei sehr unterschiedliche Dinge.
var=value sh -c 'echo "$var"'
?
"… $var …"
), aber nicht in einfache Anführungszeichen (zB '… $var …'
) gesetzt. Da echo "$var"
sich der gesamte String in einfachen Anführungszeichen befindet, wird er an die new ( sh -c
) - Shell übergeben, ohne von der äußeren, interaktiven Shell interpretiert zu werden. … (Fortsetzung)
sh -c
) untergeordneten Shell.
Ich vermute, Sie möchten Shell- Variablen haben, um einen begrenzten Bereich zu haben, anstatt Umgebungsvariablen. Umgebungsvariablen sind eine Liste von Zeichenfolgen, die bei ihrer Ausführung an Befehle übergeben werden .
Im
var=value echo whatever
Sie übergeben den var=value
String an die Umgebung, die das Echo empfängt. Tut echo
jedoch nichts mit seiner Umgebungsliste und wird sowieso in den meisten Shells echo
eingebaut und daher nicht ausgeführt .
Wenn du geschrieben hättest
var=value sh -c 'echo "$var"'
Das wäre eine andere Sache gewesen. Hier übergeben wir var=value
den sh
Befehl und sh
verwenden zufällig seine Umgebung. Shells konvertieren jede der Variablen, die sie von ihrer Umgebung erhalten, in eine Shell-Variable, sodass die var
Umgebungsvariable, die sie sh
empfängt, in eine $var
Variable konvertiert wird. Wenn sie in dieser echo
Befehlszeile erweitert wird, wird dies zu echo value
. Da die Umgebung standardmäßig vererbt wird, echo
wird sie auch var=value
in ihrer Umgebung empfangen (oder würde ausgeführt werden), echo
kümmert sich aber auch hier nicht um die Umgebung.
Nun, wenn Sie, wie ich vermute, den Umfang der Shell-Variablen einschränken möchten, gibt es mehrere mögliche Ansätze.
Portabel (Bourne und POSIX):
(var=value; echo "1: $var"); echo "2: $var"
Das obige (...) startet eine Sub-Shell (ein neuer Shell-Prozess in den meisten Shells), daher wirkt sich jede dort deklarierte Variable nur auf diese Sub-Shell aus. Daher würde ich erwarten, dass der obige Code "1: value" ausgibt. und "2:" oder "2: was-war-vorher-gesetzt".
Mit den meisten Bourne-ähnlichen Shells können Sie Funktionen und das "lokale" Builtin verwenden:
f() {
local var
var=value
echo "1: $var"
}
f
echo "2: $var"
Mit zsh können Sie Inline-Funktionen verwenden:
(){ local var=value; echo "1: $var"; }; echo "2: $var"
oder:
function { local var=value; echo "1: $var"; }; echo "2: $var"
Mit bash und zsh (aber nicht ash, pdksh oder AT & T ksh) funktioniert dieser Trick auch:
var=value eval 'echo "1: $var"'; echo "2: $var"
Eine Variante , die in ein paar mehr Granaten (funktioniert dash
, mksh
, yash
) , aber nicht zsh
(es sei denn , in sh
/ ksh
Emulation):
var=value command eval 'echo "1: $var"'; echo "2: $var"
(Die Verwendung command
vor einem speziellen (hier eval
) in POSIX-Shells beseitigt deren Besonderheit (hier bleiben die von ihnen zugewiesenen Variablen nach ihrer Rückkehr wirksam).)
Sie tun es richtig, aber die Bash - Syntax ist einfach falsch zu interpretieren: Sie könnten denken , dass echo $TEST
bewirkt , dass echo
holen TEST
env var es dann drucken, es funktioniert nicht. So gegeben
export TEST=123
dann
TEST=456 echo $TEST
beinhaltet die folgende Sequenz:
Die Shell analysiert die gesamte Befehlszeile und führt alle Variablensubstitutionen aus, sodass die Befehlszeile zu wird
TEST=456 echo 123
Es erstellt die vor dem Befehl festgelegten temporären Variablen, speichert also den aktuellen Wert von TEST
und überschreibt ihn mit 456; Die Kommandozeile ist jetzt
echo 123
Es führt den verbleibenden Befehl aus, der in diesem Fall 123 an stdout ausgibt (der verbleibende Shell-Befehl hat also nicht einmal den Temp-Wert von verwendet TEST
).
Es stellt den Wert von wieder her TEST
Verwenden Sie stattdessen printenv, da keine Variablensubstitution erforderlich ist:
>> export TEST=123
>> printenv TEST
123
>> TEST=456 printenv TEST
456
>> printenv TEST && TEST=456 printenv TEST && TEST=789 printenv TEST && printenv TEST
123
456
789
123
>>
printenv
hilfreich für das Testen / Proof of Concept (verhält sich wie ein Skript, im Gegensatz zu echo
)
Sie können dies erreichen, indem Sie verwenden:
TEST=foo && echo $TEST
TEST=foo
wird als separate Anweisung ausgeführt - es wird nicht nur im Kontext von festgelegt echo
.