Was ist der richtige Weg, um einen in einer Variable gespeicherten Befehl aufzurufen?
Gibt es Unterschiede zwischen 1 und 2?
#!/bin/sh
cmd="ls -la $APPROOTDIR | grep exception"
#1
$cmd
#2
eval "$cmd"
shell
unix
parameter-expansion
Volodymyr Bezuglyy
quelle
quelle
Antworten:
Unix-Shells führen eine Reihe von Transformationen in jeder Eingabezeile durch, bevor sie ausgeführt werden. Für die meisten Shells sieht es ungefähr so aus (aus der
bash
Manpage entnommen ):Durch die
$cmd
direkte Verwendung wird es während der Parametererweiterungsphase durch Ihren Befehl ersetzt und anschließend allen folgenden Transformationen unterzogen.Mit using
eval "$cmd"
wird nichts unternommen, bis die Phase zum Entfernen des Anführungszeichens unverändert$cmd
zurückgegeben und als Parameter an übergeben wirdeval
, dessen Funktion darin besteht, die gesamte Kette vor der Ausführung erneut auszuführen.Im Grunde sind sie in den meisten Fällen gleich und unterscheiden sich, wenn Ihr Befehl die Transformationsschritte bis zur Parametererweiterung verwendet. Beispiel: Verwenden der Klammererweiterung:
quelle
eval "$cmd"
ohne zu schreibeneval
?$($cmd)
?${$cmd}
?eval
Operation analysiert Daten als Syntax; Es ist daher sehr sicherheitsrelevant, und es implizit zu tun, wäre eine sehr schlechte Form.Wenn Sie nur tun ,
eval $cmd
wenn wir das tuncmd="ls -l"
(interaktiv und in einem Skript) wir das gewünschte Ergebnis erhalten. In Ihrem Fall haben Sie eine Pipe mit einem Grep ohne Muster, sodass der Grep-Teil mit einer Fehlermeldung fehlschlägt. Nur$cmd
wird eine "Befehl nicht gefunden" (oder eine solche) Nachricht generiert. Versuchen Sie also, eval zu verwenden, und verwenden Sie einen fertigen Befehl, der keine Fehlermeldung generiert.quelle
$cmd
würde nur die Variable durch ihren Wert ersetzen, der in der Befehlszeile ausgeführt werden soll.eval "$cmd"
Führt eine Variablenerweiterung und Befehlssubstitution durch, bevor der resultierende Wert in der Befehlszeile ausgeführt wirdDie zweite Methode ist hilfreich, wenn Sie Befehle ausführen möchten, die nicht flexibel sind, z.
for i in {$a..$b}
Die Formatschleife funktioniert nicht, da sie keine Variablen zulässt.
In diesem Fall ist eine Pipe zum Bash oder Eval eine Problemumgehung.
Getestet unter Mac OSX 10.6.8, Bash 3.2.48
quelle
Ich denke du solltest sagen
(Backtick) Symbole um Ihre Variable.
quelle