Zwischen folgenden Alternativen ...
mit
eval
.comd="ls" eval "$comd"
mit
source /dev/stdin
printf "ls" | source /dev/stdin
mit
source /dev/stdin
und( )
oder{ }
( printf "ls" ) | source /dev/stdin { printf "ls"; } | source /dev/stdin
(Wenn wir laufen
printf
in{ }
, gibt es keinen Vorteil andere als nicht Subshell verwenden?)Was ist der Unterschied zwischen ihnen?
Welches ist bevorzugt?
Welches ist die bevorzugte Methode zum Ausführen von Befehlen?
()
oder{}
?
bash
command-line
MS.Kim
quelle
quelle
Antworten:
von
bash manpage
:Es gibt keine Unterschiede zwischen den beiden Möglichkeiten.
Es gibt nur eine Anmerkung:
eval
Verkettet alle Argumente, die dann als ein einziger Befehl ausgeführt werden.source
Liest den Inhalt einer Datei und führt sie aus.eval
kann nur Befehle aus seinen Argumenten erstellen, nichtstdin
. So kann man das nicht machen:Ihr Beispiel liefert das gleiche Ergebnis, aber der Zweck von
eval
undsource
ist unterschiedlich.source
wird normalerweise verwendet, um eine Bibliothek für andere Skripte bereitzustellen, währendeval
nur Befehle ausgewertet werden. Sie sollten die Verwendungeval
nach Möglichkeit vermeiden , da keine Garantie dafür besteht, dass die ausgewertete Zeichenfolge sauber ist. wir müssensubshell
stattdessen einige Hygienekontrollen durchführen .Wenn Sie Sequenzbefehle in geschweiften Klammern
{ }
ausführen, werden alle Befehle in der aktuellen Shell und nicht in einer Subshell ausgeführt (was der Fall ist, wenn Sie in runden Klammern ausgeführt werden (siehe Bash- Referenz )).Die Verwendung von
subshell ( )
verwendet mehr Ressourcen, aber Ihre aktuelle Umgebung ist nicht betroffen. Bei Verwendung von werden{ }
alle Befehle in der aktuellen Shell ausgeführt, sodass Ihre Umgebung betroffen ist. Abhängig von Ihrem Zweck können Sie einen davon auswählen.quelle
eval
durchsource
. Ich denke die Frage ist: Isteval "$cmd"
gleichbedeutend mitecho "$cmd" | source /dev/stdin
. Meine aktuelle Meinung ist: ja.Der Hauptunterschied besteht darin, dass die 2. und 3. Form eine Pipe verwenden, mit der Bash gezwungen wird, den Befehl "source" in einer Subshell auszuführen (es sei denn, die letzte Pipe ist festgelegt, nur in Bash 4.2+ verfügbar) :
Die Konsequenzen sind, dass alle von Ihrem Code gesetzten Umgebungsvariablen verloren gehen und dies nicht wie erwartet funktioniert:
Um die Befehle in der aktuellen Shell auszuführen, können Sie die Prozessersetzung verwenden:
Sie können wie gewohnt weitere Befehle in Klammern setzen, indem Sie ein Semikolon verwenden.
Wenn Sie die Pipe auf diese Weise entfernen, gibt es meines Erachtens keinen Unterschied zwischen der Verwendung von "eval" und "source". Sie sollten diejenige vorziehen, die in Ihrem speziellen Fall einfacher zu verwenden ist:
quelle
Ergänzend zu den bereits gegebenen Antworten:
Ein
source
Äquivalent zu ...... ist ...
Im Falle
ls
gibt es keinen signifikanten Unterschied.Aber im Falle eines Befehls, der Ihre aktuelle Umgebung beeinflussen soll (was Sie normalerweise bei der Verwendung beabsichtigen
source
), würde diese Variante dies tun (wie Ihre erste Lösungeval
auch), während Ihr zweiter Ansatz nur die Umgebung einer Unterschale betrifft, die gewonnen hat. ' Nicht verfügbar, nachdem Sie Ihre Codezeile ausgeführt haben.quelle