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.
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-issuebash
kann in ausgeführt werden Die obere Shell hängt von den Optionen ab, aberx=42
wird sicher in etwas ausgeführt, das vernünftigerweise als Subshell bezeichnet werden kann.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.