1249 Stimmen

Definieren einer Variable mit oder ohne Export

Wofür ist export?

Was ist der Unterschied zwischen:

export name=value

und

name=value

2 Stimmen

1364voto

Brian Agnew Punkte 260470

export stellt die Variable sub-Prozessen zur Verfügung.

Das bedeutet,

export name=value

bedeutet, dass die Variable name für jeden Prozess verfügbar ist, den Sie von diesem Shell-Prozess ausführen. Wenn Sie möchten, dass ein Prozess diese Variable verwendet, verwenden Sie export und führen Sie den Prozess von dieser Shell aus.

name=value

bedeutet, dass der Geltungsbereich der Variable auf die Shell beschränkt ist und für keinen anderen Prozess verfügbar ist. Sie würden dies für (zum Beispiel) Schleifenvariablen, temporäre Variablen usw. verwenden.

Es ist wichtig zu beachten, dass das Exportieren einer Variable diese nicht für übergeordnete Prozesse verfügbar macht. Das bedeutet, dass das Angeben und Exportieren einer Variable in einem abgeleiteten Prozess sie nicht im Prozess verfügbar macht, der ihn gestartet hat.

131 Stimmen

Speziell export macht die Variable über die Umgebung für Kindprozesse verfügbar.

24 Stimmen

Ich würde auch hinzufügen, dass wenn der Export in einer Datei erfolgt, die Sie "sourcen" (wie z.B. . Dateiname), dann wird er auch in Ihre Arbeitsumgebung exportiert.

10 Stimmen

@rogerdpack kannst du das ohne Export machen? cat > blah \n a=hi \n . blah; echo $a; gibt 'hi' für mich aus.

343voto

alxp Punkte 5876

Um zu veranschaulichen, was die anderen Antworten sagen:

$ foo="Hallo, Welt"
$ echo $foo
Hallo, Welt
$ bar="Auf Wiedersehen"
$ export foo
$ bash
bash-3.2$ echo $foo
Hallo, Welt
bash-3.2$ echo $bar

bash-3.2$

13 Stimmen

Ein weiteres Beispiel für diesen al$ foobar="WasAuchImmer" bash

1 Stimmen

Nur für den Fall, dass jemand dies in Bash mit Arrays ausprobieren möchte (wie ich es getan habe...), hier ein Hinweis: es geht nicht.

98voto

Matyas Koszik Punkte 1037

Es wurde gesagt, dass es nicht notwendig ist, in Bash zu exportieren, wenn Unterprozesse gestartet werden, während andere genau das Gegenteil behaupten. Es ist wichtig, den Unterschied zwischen Unterprozessen (die durch (), ``, $() oder Schleifen erstellt werden) und Teilprozessen (Prozesse, die durch Namen aufgerufen werden, zum Beispiel ein wörtliches bash in Ihrem Skript) zu beachten.

  • Subshells haben ungeachtet ihres Exportzustands Zugriff auf alle Variablen des übergeordneten Prozesses.
  • Subprozesse sehen nur die exportierten Variablen.

Was in diesen beiden Konstrukten gemeinsam ist, ist, dass weder Variablen an den übergeordneten Shellprozess zurückgegeben werden können.

$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess
subshell: noexport export
subprocess: export
parent:

Es gibt eine weitere Quelle der Verwirrung: Manche glauben, dass 'geforkte' Teilprozesse diejenigen sind, die nicht auf nicht exportierte Variablen zugreifen können. Normalerweise werden fork()s sofort von exec()s gefolgt, und deshalb scheint es, dass man nach dem fork() suchen muss, während es in Wirklichkeit das exec() ist. Sie können Befehle ohne vorheriges Forking mit dem Befehl exec ausführen, und Prozesse, die auf diese Weise gestartet werden, haben ebenfalls keinen Zugriff auf nicht exportierte Variablen:

$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export

Beachten Sie, dass wir dieses Mal die parent: Zeile nicht sehen, da wir die übergeordnete Shell durch den exec Befehl ersetzt haben, sodass nichts übrig bleibt, um diesen Befehl auszuführen.

0 Stimmen

Ich habe noch nie eine Schleife gesehen, die (von selbst) eine Unter-Shell erstellt hat; andererseits erstellt eine Pipeline (immer für Teile außer dem letzten, manchmal für den letzten abhängig von Ihrer Shell, Version und Optionen) eine Unter-Shell. Das Hintergrundsetzen (&) erstellt ebenfalls eine Unter-Shell.

2 Stimmen

Was ist mit diesen var=asdf bash -c 'echo $var' oder var=asdf exec bash -c 'echo $var'? Die Ausgabe ist asdf. Das ; macht einen Unterschied, wenn es nach der Variablendefinition platziert wird. Was wäre die Erklärung? Es sieht so aus, als ob das var (ohne ;) sich irgendwie auf den gestarteten Prozess bezieht, da die Ursprungsshell nichts damit zu tun hat. echo $var gibt nichts aus, wenn es in der zweiten Zeile ausgeführt wird. Aber in einer Zeile var=asdf bash -c 'echo $var'; echo $var ergibt asdf\nasdf.

1 Stimmen

@4xy Das ist ein ganz anderer Fall; var=value command setzt die Variable var auf den Wert value für die Dauer des Befehls command in der Umgebung dieses Befehls. Dies ist vage ähnlich zu dem, was der Befehl env macht.

87voto

William Pursell Punkte 188248

Dies ist eine falsche Antwort, die jedoch aus historischen Gründen beibehalten wurde. Siehe unten die 2. Bearbeitung.

Andere haben geantwortet, dass export die Variable für Unter-Shell verfügbar macht, und das ist korrekt, aber nur ein Nebeneffekt. Wenn Sie eine Variable exportieren, platziert sie diese Variable in die Umgebung der aktuellen Shell (d. h. die Shell ruft putenv(3) oder setenv(3) auf).
Die Umgebung eines Prozesses wird bei exec vererbt, wodurch die Variable in Unter-Shell sichtbar wird.

Bearbeitung (mit 5 Jahren Perspektive): Dies ist eine alberne Antwort. Der Zweck von 'export' besteht darin, Variablen "in der Umgebung von anschließend ausgeführten Befehlen zu sein", ob diese Befehle Unter-Shell oder Unterprozesse sind. Eine naive Implementierung wäre es, die Variable einfach in die Umgebung der Shell zu setzen, aber dadurch wäre es unmöglich, export -p zu implementieren.

2. Bearbeitung (weitere 5 Jahre sind vergangen). Diese Antwort ist einfach bizarr. Möglicherweise hatte ich irgendwann einen Grund zu behaupten, dass bash die exportierte Variable in ihre eigene Umgebung setzt, aber diese Gründe wurden hier nicht angegeben und sind jetzt verloren gegangen. Siehe Exportieren einer funktionslokalen Variable in die Umgebung.

8 Stimmen

Bitte beachten Sie, dass dies nicht ganz korrekt ist. In bash fügt export die Variable tatsächlich zur Umgebung der aktuellen Shell hinzu, aber das ist bei dash nicht der Fall. Es scheint mir, dass das Hinzufügen der Variable zur Umgebung der aktuellen Shell der einfachste Weg ist, um die Semantik von export zu implementieren, aber dieses Verhalten ist nicht vorgeschrieben.

8 Stimmen

Ich bin mir nicht sicher, was dash damit zu tun hat. Der Original-Poster hat speziell nach bash gefragt.

18 Stimmen

Die Frage ist mit bash getaggt, gilt jedoch gleichermaßen für jede Bourne-Shell-Variante. Es ist sehr schlimm, übermäßig spezifisch zu sein und Antworten zu geben, die nur für bash gelten.

39voto

Charles Merriam Punkte 18484

export NAME=value für Einstellungen und Variablen, die für einen Unterprozess eine Bedeutung haben.

NAME=value für temporäre oder Schleifenvariablen, die privat für den aktuellen Shell-Prozess sind.

Im Detail markiert export den Variablennamen in der Umgebung, der in Unterprozessen und deren Unterprozessen beim Erstellen kopiert wird. Es wird nie ein Name oder Wert aus dem Unterprozess zurückkopiert.

  • Ein häufiger Fehler ist es, ein Leerzeichen um das Gleichheitszeichen zu setzen:

    $ export FOO = "bar"  
    bash: export: `=': not a valid identifier
  • Nur die exportierte Variable (B) wird vom Unterprozess gesehen:

    $ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash
    A is . B is Bob
  • Änderungen im Unterprozess ändern nicht die Hauptshell:

    $ export B="Bob"; echo 'B="Banana"' | bash; echo $B
    Bob
  • Markierte Variablen für den Export haben Werte, die beim Erstellen des Unterprozesses kopiert werden:

    $ export B="Bob"; echo '(sleep 30; echo "Subprozess 1 hat B=$B")' | bash &
    [1] 3306
    $ B="Banana"; echo '(sleep 30; echo "Subprozess 2 hat B=$B")' | bash 
    Subprozess 1 hat B=Bob
    Subprozess 2 hat B=Banana
    [1]+  Done         echo '(sleep 30; echo "Subprozess 1 hat B=$B")' | bash
  • Nur exportierte Variablen werden Teil der Umgebung (man environ):

     $ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
     BOB=Bob

Also, jetzt sollte klar sein wie die Sonne im Sommer! Danke an Brain Agnew, alexp und William Prusell.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X