Wann wird ein Semikolon zwischen Umgebungsvariablen und einem Befehl verwendet?

Wann wird ein Semikolon zwischen Umgebungsvariablen und einem Befehl verwendet?

Kann jemand erklären, warum das Semikolon notwendig ist, damit es LANGvon Bash als aktualisiert angezeigt wird?

Funktioniert nicht:

> LANG=Ja_JP bash -c "echo $LANG"
en_US

Werke:

> LANG=Ja_JP ; bash -c "echo $LANG"
Ja_JP

Ich arbeite sowohl mit Bash 4.1.10 unter Linux als auch mit der gleichen Version unter Cygwin

Antwort1

Parameter- und andere Erweiterungen werden beim Lesen des Befehls durchgeführt,Vores wird ausgeführt.

Die erste Version, LANG=Ja_JP bash -c "echo $LANG", ist ein einzelner Befehl. Nachdem er als solcher analysiert wurde, $LANGwird er zu erweitert, en_USbevor irgendetwas ausgeführt wird. Sobald bashdie Verarbeitung der Eingabe abgeschlossen ist, verzweigt er einen Prozess, fügt ihn LANG=Ja_JPwie erwartet zur Umgebung hinzu und führt dann aus bash -c echo en_US.

Sie können die Erweiterung mit einfachen Anführungszeichen verhindern, d. h. es LANG=Ja_JP bash -c 'echo $LANG'werden Ausgaben ausgegeben Ja_JP.

Beachten Sie, dass sich eine Variablenzuweisung als Teil eines Befehls nur auf die Umgebung dieses Befehls auswirkt, nicht jedoch auf die Ihrer Shell.

Bei der zweiten Version LANG=Ja_JP; bash -c "echo $LANG"handelt es sich eigentlich um zwei separate Befehle, die nacheinander ausgeführt werden. Der erste ist eine einfache Variablenzuweisung ohne Befehl und wirkt sich daher auf Ihre aktuelle Shell aus.

Daher unterscheiden sich Ihre beiden Snippets trotz des oberflächlichen Unterschieds eines einzelnen grundlegend ;.

Völlig abseits des Themas, aber ich würde empfehlen, eine .UTF-8„when“-Einstellung anzuhängen LANG. Es gibt heutzutage keinen guten Grund, Unicode nicht zu verwenden.

Antwort2

VAR=value; somecommandist äquivalent zu

VAR=value
somecommand

Dies sind unabhängige Befehle, die nacheinander ausgeführt werden. Der erste Befehl weist der Shell-Variable einen Wert zu VAR. Sofern VARes sich nicht bereits um eine Umgebungsvariable handelt, wird sie nicht in die Umgebung exportiert, sondern bleibt intern in der Shell. Eine Anweisung export VARwürde in die Umgebung exportieren VAR.

VAR=value somecommandist eine andere Syntax. Die Zuweisung VAR=valueerfolgt an die Umgebung, aber diese Zuweisung wird nur in der Ausführungsumgebung von vorgenommen somecommand, nicht für die nachfolgende Ausführung der Shell.

Als Beispiel:

# Assume neither VAR1 nor VAR2 is in the environment
VAR1=value
echo $VAR1                        # displays "value"
env | grep '^VAR1='               # displays nothing
VAR2=value env | grep '^VAR2='    # displays "VAR2=value"
echo $VAR2                        # displays nothing

Antwort3

Dies ist die Zusammenfassung meiner Rechercheergebnisse:

Es gibt zwei Typen: Umgebungsvariablen und Shellvariablen.

Eine Umgebungsvariable ist in einem Programm und seinen untergeordneten Programmen/Prozessen/Sub-Shells verfügbar. Eine Shell-Variable ist nur in der aktuellen Shell verfügbar.

https://askubuntu.com/a/26322/326584

Wie echo $VARfunktioniert es?

Immer wenn ein Terminal/eine Shell/eine Bash das Symbol $ sieht, führt es etwas aus, das als „Parametererweiterung“ bezeichnet wird. Das bedeutet, dass Variablen durch Werte ersetzt werden.

https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html

Wenn also VARder Wert „Hallo“ war, echo $VARwird daraus echo 'hello'.

was bedeutet, dass dies funktioniert ...

TEST=123 
echo $TEST
// 123

aber das Folgende funktioniert nicht, weil die Variable ersetzt wurde, BEVOR der Befehl die Variable festlegen konnte.

TEST2=999 echo $TEST2
// nothing...

aber wenn Sie das Semikolon hinzufügen...

TEST2=999; echo $TEST2

es ist dasselbe wie..

TEST2=999
echo $TEST2

.. das funktioniert genauso wie zuvor.

Und da Shell-Variablen nicht an Unterprozesse/untergeordnete Prozesse übergeben werden, wird beim Aufrufen eines Befehls ein neuer Prozess erstellt, also ...

TEST3=111 
node -e 'console.log(process.env.TEST3)' 

oder

TEST3=111 
printenv TEST3

beide geben nichts aus. Shell-Variablen werden nicht von untergeordneten Prozessen übernommen. Verwenden Sie „export“, um aus einer Shell-Variable eine Umgebungsvariable zu machen.

export TEST3=111 
printenv TEST3
//111

Es gibt eine Ausnahme …

VAR=123 printenv VAR
VAR=123 VAR2=456 printenv VAR2 //even multiple vars

Wenn man es so schreibt und direkt nach dem Aufruf des Befehls, legt es grundsätzlich nur vorübergehend die Umgebungsvariable für diesen Befehl fest. Es legt nicht einmal die Shellvariable fest. Betrachten Sie es als eine völlig neue Syntax.

VAR=123 printenv VAR // 123
echo $VAR // nothing
VAR=123
echo $VAR // 123

verwandte Informationen