Aufzucht und Hege von Shell-Scripts: Wahr und Falsch
Was ist wahr, was ist falsch?
Über den Returncode von Programmen habe ich schon oben in Fehler geplaudert. Diese Unterscheidung (0 = OK, ungleich 0 = Fehler) gilt aber auch beim Evaluieren von Ausdrücken: 0 = Wahr, ungleich 0 = Falsch. Das Shell-Builtin test macht auch nichts anderes: Es liefert 0 als Returncode, wenn der zu testende Ausdruck wahr ist, ansonsten 1. Probiert es aus:
jan@jack:~/tmp> test 1 -eq 1 jan@jack:~/tmp> echo $? 0 jan@jack:~/tmp> test 1 -eq 2 jan@jack:~/tmp> echo $? 1
Es ist also problemlos möglich, den Returncode jedes Programms z. B. in if-Abfragen oder als Abbruchbedingung in Schleifen direkt zu nutzen, diese Kontrollstrukturen werten nämlich auch nur aus, ob ihr Argument 0 oder nicht 0 ist. Oft sieht man hier unnötig komplizierte Konstruktionen, die man deutlich einfacher formulieren könnte:
# pruefen, ob ein bestimmtes Suchmuster in einer Datei enthalten ist
# unschoen
if test `grep Suchmuster Datei | wc -l` -gt 0; then
...
fi
# einfacher
if grep -q Suchmuster Datei; then
...
fi
# Schleife, solange noch .bak-Dateien vorhanden sind
# unschoen
while true; do
anz_bak_files=`ls *.bak 2>/dev/null | wc -l`
test $anz_bak_files -eq 0 && break
...
done
# einfacher
while ls *.bak >/dev/null 2>>&1; do
...
done
Übrigens, das in der while-Schleife genutzte true ist ein Shell-Builtin, das einfach immer 0 als Returnwert liefert, sein Gegenpart ist - genau - false.
Einen hab ich noch: Ihr habt in den Beispielen ab und zu mal solche Konstruktionen gesehen:
Befehl1 && Befehl2 oder
Befehl1 || Befehl2
Das sind in Wirklichkeit einfach UND- bzw. ODER-Bedingungen. Die
o. g. Befehlsverknüpfungen machen sich zu Nutze, dass die Shell genaus so faul ist wie die meisten Programmierer:
- Eine UND-Bedingung ist nur dann Wahr, wenn beide Operanden (in dem Beispiel die Returncodes beider Befehle) wahr, also 0 sind. Wenn Befehl1 einen Returncode ungleich 0 liefert (also einen Fehler), dann ist klar, dass die Bedingung nur falsch sein kann, damit wird auf das Evaluieren (also Ausführen) von Befehl2 verzichtet, da sein Returncode keinen Einfluss mehr auf das Ergebnis hat. Damit wird Befehl2 nur dann ausgeführt, wenn Befehl1 erfolgreich war.
- Eine ODER-Bedingung ist dann Wahr, wenn mindestens einer der Operanden wahr, also 0 ist. Wenn Befehl1 einen Returncode 0 liefert (also erfolgreich war), dann ist klar, dass die Bedingung wahr sein muss, Befehl2 wird dann nicht mehr ausgeführt. Nur wenn Befehl1 einen Fehler (Returnwert ungleich 0) lieferte, muss Befehl2 noch ausgeführt werden, um zu ermitteln, wie die Bedingung endet.
Damit ist auch klar, dass man den Returncode der gesamten Verknüpfung mit Vorsicht betrachten muss, er ist nämlich nicht in jedem Fall eindeutig: Nur wenn die UND-Bedingung Wahr (also 0) ist, dann ist klar, dass beide Kommandos erfolgreich waren. Ist sie Falsch, dann ist nur klar, dass eines der beiden Kommandos einen Fehler lieferte, welches, das ist nicht zu ermitteln. Für die ODER-Bedingung ist es genau anders rum: Nur wenn sie Falsch (also ungleich 0) liefert, dann ist klar, dass beide Kommandos einen Fehler lieferten, wenn sie Wahr (also 0) liefert, dann ist eines der Kommandos erfolgreich gewesen, welches, das ist nicht definiert.

