eval vs. pipe through bash (Deutsch)

Was ist der Unterschied zwischen der Verwendung von:

eval "echo "foo"" 

und

echo "echo "foo"" | bash 

gibt es welche?

Kommentare

  • Hier ' ist eine weitere Variante mit leicht unterschiedlichem Verhalten in Bezug auf Ausführungsumgebungen: ( eval 'echo "foo"' )

Antwort

Kurze Antwort

Der von eval ausgeführte Befehl wird in der aktuellen Shell ausgeführt, und der an bash weitergeleitete Befehl wird in einer Unter-Shell ausgeführt, z. B.:

> echo "x=42" | bash; echo $x > eval "x=42"; echo $x 42 

Längere Antwort

In den Kommentaren wurde die Behauptung aufgestellt, dass in neueren Versionen von bash (> = 4.2) Der erste Befehl könnte auch den gleichen Effekt haben. Dies scheint jedoch nicht der Fall zu sein.

Es gibt tatsächlich einige Faktoren, die dazu führen, dass der Piped-Befehl in der aktuellen Sitzung nicht ausgeführt wird: die Pipe und die bash.

Piped-Befehle werden größtenteils in Subshells ausgeführt. Das Bash-Handbuch ( Abschnitt 3.2.2: Pipelines ) enthält Folgendes:

Jeder Befehl in einer Pipeline wird in einer eigenen Subshell ausgeführt (siehe Befehlsausführungsumgebung ).

Wie in den Kommentaren erwähnt, kann dieses Verhalten über die Option lastpipe geändert werden. Das Bash-Handbuch ( Abschnitt 4.3.2: The Shopt Builtin ) enthält Folgendes zur Option lastpipe:

lastpipe

Wenn gesetzt und die Jobsteuerung nicht aktiv ist, führt die Shell den letzten Befehl einer Pipeline aus, die nicht in der ausgeführt wird Hintergrund in der aktuellen Shell-Umgebung.

Wir können dies wie folgt überprüfen.

Aktivieren Sie zuerst lastpipe:

> shopt -s lastpipe 

Deaktivieren Sie dann die Jobsteuerung:

> set +m 

Führen Sie nun einen Befehl aus, der eine Variable innerhalb einer Pipe festlegt:

> unset x > echo x=42 | while IFS= read -r line; do eval "${line}"; done; > echo $x 42 

Beachten Sie, dass wir die while loop und read Befehl als Umgehung, da der Befehl eval seine Eingabe nicht von stdin lesen kann (daher seine Eingabe nicht von erhalten kann) eine Pipe).

Dieses Beispiel zeigt, dass der Befehl ganz rechts in der Pipe tatsächlich kann , in der aktuellen Shell ausgeführt werden. Dies hat jedoch keinen Einfluss auf unser ursprüngliches Beispiel. Selbst wenn lastpipe aktiviert und die Jobsteuerung deaktiviert ist, erhalten wir beim Weiterleiten an bash das folgende Ergebnis:

> echo "x=42" | bash; echo $x > 

Dies liegt daran, dass der Befehl bash selbst seine Eingabe in einer Unterschale ausführt.

Kommentare

  • das ist eine gute Beobachtung, ' hat das nicht bemerkt, aber ja, ich denke, dass ' s wie Pipes funktionieren
  • Nur neugierig, was ist der Grund, warum Sie die Antwort nicht akzeptiert haben?
  • Für Bash 4.2+ beim Ausführen eines Skripts (oder genauer, wenn Jobcontrol deaktiviert ist) und shopt lastpipe ist gesetzt und die Pipeline hat keinen Hintergrund. Sie führt das rechte Ende der Pipe in der ' top ' Shell ist keine Subshell. Siehe unix.stackexchange.com/questions/9954/… und unix.stackexchange.com/questions/136206/readarray-or-pipe-issue
  • @ dave_thompson_085 Der Befehl bash kann in ausgeführt werden Die obere Shell hängt von den Optionen ab, aber x=42 wird sicher in etwas ausgeführt, das vernünftigerweise als Subshell bezeichnet werden kann.
  • @AlexanderMills Tatsächlich ist die Pipe nicht ' ist das einzige Problem. Der Befehl bash führt seine Eingabe in einer Subshell aus, unabhängig davon, ob eine Pipe beteiligt ist oder nicht. Weitere Informationen finden Sie im Update zu meiner Lösung.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.