Es scheint hier ein Missverständnis über das integrierte Bash-true
zu geben, genauer gesagt darüber, wie Bash Ausdrücke innerhalb von Klammern erweitert und interpretiert.
Der Code in mikus Antwort hat absolut nichts mit dem integrierten Bash-true
zu tun, auch nicht mit /bin/true
oder einer anderen Variante des true
-Befehls. In diesem Fall ist true
nichts weiter als eine einfache Zeichenkette, und es wird weder durch die Variablenzuweisung noch durch die Auswertung des bedingten Ausdrucks jemals ein Aufruf des true
-Befehls/integriertes gemacht.
Der folgende Code ist funktional identisch mit dem Code in mikus Antwort:
the_world_is_flat=ja
if [ "$the_world_is_flat" = ja ]; then
echo 'Pass auf, dass du nicht runterfällst!'
fi
Der einzige Unterschied hier besteht darin, dass die vier verglichenen Zeichen 'j', 'a', 'e' und 'h' anstelle von 't', 'r', 'u' und 'e' sind. Das war's. Es wird kein Versuch unternommen, einen Befehl oder ein eingebautes Programm namens ja
aufzurufen, und es findet (im Beispiel von miku) keine spezielle Behandlung statt, wenn Bash das Token true
analysiert. Es ist einfach eine Zeichenkette und eine völlig beliebige noch dazu.
Update (2014-02-19): Nachdem ich dem Link in mikus Antwort gefolgt bin, verstehe ich jetzt, woher etwas von der Verwirrung kommt. Mikus Antwort verwendet eckige Klammern, aber das von ihm verlinkte Code-Snippet verwendet keine Klammern. Es lautet einfach:
the_world_is_flat=true
if $the_world_is_flat; then
echo 'Pass auf, dass du nicht runterfällst!'
fi
Beide Code-Snippets verhalten sich genauso, aber die Klammern ändern vollständig, was im Hintergrund passiert.
Das macht Bash in jedem Fall:
Keine Klammern:
- Erweitere die Variable
$the_world_is_flat
zur Zeichenkette "true"
.
- Versuche, die Zeichenkette
"true"
als Befehl zu analysieren.
- Den
true
-Befehl finden und ausführen (entweder ein eingebauter oder /bin/true
, je nach Bash-Version).
- Vergleiche den Exit-Code des
true
-Befehls (der immer 0 ist) mit 0. Beachte, dass in den meisten Shells ein Exit-Code von 0 Erfolg und alles andere Misserfolg bedeutet.
- Da der Exit-Code 0 (Erfolg) war, führe die
then
-Klausel des if
-Statements aus.
Klammern:
- Erweitere die Variable
$the_world_is_flat
zur Zeichenkette "true"
.
- Analysiere den nun vollständig erweiterten bedingten Ausdruck, der die Form
string1 = string2
hat. Der =
-Operator ist Bashes Zeichenkettenvergleichs-Operator. Also...
- Führe einen Zeichenkettenvergleich zwischen
"true"
und "true"
durch.
- Ja, die beiden Zeichenketten waren identisch, also ist der Wert der Bedingung wahr.
- Führe die
then
-Klausel des if
-Statements aus.
Der Code ohne Klammern funktioniert, weil der true
-Befehl einen Exit-Code von 0 zurückgibt, was Erfolg bedeutet. Der in Klammern stehende Code funktioniert, weil der Wert von $the_world_is_flat
mit der Zeichenkettenliteralen true
auf der rechten Seite des =
identisch ist.
Um das zu verdeutlichen, betrachte die folgenden beiden Code-Snippets:
Dieser Code (wenn mit Root-Berechtigungen ausgeführt) wird deinen Computer neu starten:
var=neustarten
if $var; then
echo 'Muahahaha! Du gehst unter!'
fi
Dieser Code druckt nur "Schöner Versuch." Der Neustart-Befehl wird nicht aufgerufen.
var=neustarten
if [ $var ]; then
echo 'Schöner Versuch.'
fi
Update (2014-04-14) Um die Frage in den Kommentaren zur Differenz zwischen =
und ==
zu beantworten: Nach meinem Kenntnisstand gibt es keinen Unterschied. Der ==
-Operator ist ein Bash-spezifisches Synonym für =
, und soweit ich gesehen habe, funktionieren sie in allen Kontexten genau gleich.
Es sei jedoch darauf hingewiesen, dass ich speziell über die =
und ==
Zeichenkettenvergleichsoperatoren in [ ]
oder [[ ]]
-Tests spreche. Ich möchte nicht behaupten, dass =
und ==
überall in Bash austauschbar sind.
Zum Beispiel kann man offensichtlich keine Variablenzuweisung mit ==
machen, wie z.B. var=="foo"
(technisch gesehen kannst du das tun, aber der Wert von var
wird "=foo"
sein, weil Bash hier keinen ==
-Operator sieht, sondern einen =
(Zuweisung) -Operator, gefolgt von dem Literalwert ="foo"
, was einfach zu "=foo"
wird).
Außerdem, obwohl =
und ==
austauschbar sind, sollte man beachten, dass die Funktionsweise dieser Tests davon abhängt, ob sie innerhalb von [ ]
oder [[ ]]
verwendet werden und ob die Operanden in Anführungszeichen stehen. Mehr dazu findest du im Advanced Bash Scripting Guide: 7.3 Other Comparison Operators (scrolle zur Diskussion über =
und ==
).