Warum funktioniert dieser Bash -Code nicht?
Frage
x="a=b"
`echo $x`
echo $a
Ich erwarte, dass die zweite Zeile "a = b" generiert und im Kontext der Haupthülle ausführt, was zu einer neuen Variablen führt a
mit Wert b
. Was ich jedoch wirklich bekomme (wenn ich die Befehle manuell eingehe) ist die Fehlermeldung nach der zweiten Zeile, bash: a=b: command not found
Warum ist das so?
Lösung
Es liegt an der Reihenfolge, in der Bash die Befehlszeile analysiert. Es sucht nach variablen Definitionen (z. B. nach zB a=b
) Vor Variable und Befehlssubstitution (z. B. Befehle in Backticks) durchführen. Aus diesem Zeitpunkt zu diesem Zeitpunkt echo $x
wird durch a=b
, Es ist zu spät für Bash, dies als eine variable Definition zu sehen, und es wird stattdessen als Befehl analysiert. Das gleiche wäre passiert, wenn Sie gerade benutzt hätten $x
als Befehl (anstelle von Echo in Backticks). Wie in der Antwort von @mvds, die eval
Der Befehl kann verwendet werden, um den Befehl von Anfang an zu erzwingen, was bedeutet, dass er als variable Definition erkannt wird:
$ x="a=b"
$ `echo $x`
-bash: a=b: command not found
$ $(echo $x) # Exact same thing, but with cleaner syntax
-bash: a=b: command not found
$ $x # This also does the same thing, but without some extra steps
-bash: a=b: command not found
$ eval "$x" # This will actually work
$ echo $a
b
$ a= # Start over
$ eval "$(echo "$x")" # Another way of doing the same thing, with extra steps
$ echo $a
b
Beachten Sie das, wenn Sie verwendet werden eval
Ich habe alle Referenzen gestellt $x
In Doppelquoten-dies soll verhindern, dass die späteren Phasen des Bash-Parsens (z. B. Wortaufteilung) stattfinden zweimal, da Bash seinen regelmäßigen Parsing -Prozess beenden und dann das erkennen eval
Befehl und dann den gesamten Parsingprozess wiederholen wieder. Es ist wirklich einfach, unerwartete Ergebnisse durch die Verwendung zu erzielen eval
, und dies beseitigt zumindest ein Teil des Potenzials für Schwierigkeiten.
Andere Tipps
Versuchen
eval $x
(Und wir brauchen 30 Zeichen, damit diese Antwort veröffentlicht werden soll)
Ihre erste Echo -Linie läuft in einer Unterschale und gibt ihren Wert an den Callee zurück. Das gleiche Ergebnis wird mit Verwendung erzielt $()
und ist übrigens einfacher zu bedienen als Backticks.
Also, was Sie tun, läuft zum ersten Mal echo $x
(was kehrt zurück a=b
). Und wegen der Backticks, a=b
wird in die Shell zurückgegeben, die versucht, diese Zeile als Befehl auszuführen, die - offensichtlich - nicht funktionieren wird.
Versuchen Sie dies in einer Shell:
$(echo ls)
Und Sie werden deutlich sehen, was passiert.
Hast du versucht $x
In diesem lustigen Apostrophe? Ohne echo
, Echo scheint nur für die Anzeige von String zu sein und keine Befehle auszuführen.