Inhaltsverzeichnis
Eine der grundlegendsten Dinge beim Programmieren ist die Überprüfung von verschiedenen Bedingungen, um damit auf bestimmte Gegebenheiten zu reagieren. Die Überprüfung von Bdingungen hat in der Regel bei Programmiersprachen zwei verschiedene Formen, die if-Anweisung und eine Mehrfachauswahl. Beide werden von der Shell unterstützt.
1. Die if-Anweisung unter Bash
1.1 Die einfache if-Anweisung
Grundsätzlich hat die if-Anweisung der Bourne-Shell eine sehr einfache Form. Nach dem if steht ein Befehl, der ausgeführt wird. Gibt dieses Kommando eine 0 als Rückgabewert zurück, so gilt die Bedingung als erfüllt und die Aktionen, die zwischen dem folgenden then und fi stehen werden ausgeführt.
if Kommando then Aktion Aktion ... fi
Natürlich sind die Aktionen auch wieder normale Unix-Befehle. Das „fi“, das den Block beendet, der durch „if … then“ begonnen wurde, ist einfach nur das „if“ rückwärts geschrieben.
1.2 Das Programm test
Damit es jetzt sinnvolle Möglichkeiten gibt, Bedingungen zu überprüfen brauchen wir ein Programm, das verschiedene Tests durchführt und jeweils bei gelungenem Test eine 0 als Rückgabewert zurückgibt, bei mislingenem Test eine 1. Dieses Programm heißt test und ermöglicht alle wesentlichen Bedingungsüberprüfungen, die für das Shell-Programmieren notwendig sind.
Damit wir nicht jedesmal schreiben müssen
if test ...
gibt es einen symbolischen Link auf das Programm test, der einfach [ heißt. Allerdings verlangt das Programm test, wenn es merkt, dass es als [ aufgerufen wurde, auch als letzten Parameter eine eckige Klammer zu. Damit ist es also möglich zu schreiben:
if [ ... ]
Wichtig ist hierbei, dass unbedingt ein Leerzeichen zwischen if und der Klammer und zwischen der Klammer und den eigentlichen Tests stehen muß. Es handelt sich bei der Klammer ja tatsächlich um einen Programmaufruf!
1.3 Die verschiedenen Bedingungsüberprüfungen mit test bzw. [
-r Dateiname
Die Datei Dateiname existiert und ist lesbar
-w Dateiname
Die Datei Dateiname existiert und ist beschreibbar
-x Dateiname
Die Datei Dateiname existiert und ist ausführbar
-d Dateiname
Die Datei Dateiname existiert und ist ein Verzeichnis
-s Dateiname
Die Datei Dateiname existiert und ist nicht leer
-b Dateiname
Die Datei Dateiname existiert und ist ein blockorientiertes Gerät
-c Dateiname
Die Datei Dateiname existiert und ist ein zeichenorientiertes Gerät
-g Dateiname
Die Datei Dateiname existiert und das SGID-Bit ist gesetzt
-k Dateiname
Die Datei Dateiname existiert und das Sticky-Bit ist gesetzt
-u Dateiname
Die Datei Dateiname existiert und das SUID-Bit ist gesetzt
-p Dateiname
Die Datei Dateiname existiert und ist ein Named Pipe
-e Dateiname
Die Datei Dateiname existiert
-f Dateiname
Die Datei Dateiname existiert und ist eine reguläre Datei
-L Dateiname
Die Datei Dateiname existiert und ist ein symbolischer Link
-S Dateiname
Die Datei Dateiname existiert und ist ein Socket
-O Dateiname
Die Datei Dateiname existiert und ist Eigentum des Anwenders, unter dessen UID das test-Programm gerade läuft
-G Dateiname
Die Datei Dateiname existiert und gehört zu der Gruppe, zu der der User gehört, unter dessen UID das test-Programm gerade läuft
Datei1 -nt Datei2
Datei1 ist neuer als Datei2 (newer than)
Datei1 -ot Datei2
Datei1 ist älter als Datei2 (older than)
Datei1 -ef Datei2
Datei1 und Datei2 benutzen die gleiche I-Node (equal file)
-z Zeichenkette
Wahr wenn Zeichenkette eine Länge von Null hat.
-n Zeichenkette
Wahr wenn Zeichenkette eine Länge von größer als Null hat.
Zeichenkette1 = Zeichenkette2
Wahr wenn Zeichenkette1 gleich Zeichenkette2
Zeichenkette1 != Zeichenkette2
Wahr wenn Zeichenkette1 ungleich Zeichenkette2
Wert1 -eq Wert2
Wahr, wenn Wert1 gleich Wert2 (equal)
Wert1 -ne Wert2
Wahr, wenn Wert1 ungleich Wert2 (not equal)
Wert1 -gt Wert2
Wahr, wenn Wert1 größer Wert2 (greater than)
Wert1 -ge Wert2
Wahr, wenn Wert1 größer oder gleich Wert2 (greater or equal)
Wert1 -lt Wert2
Wahr, wenn Wert1 kleiner Wert2 (less than)
Wert1 -le Wert2
Wahr, wenn Wert1 kleiner oder gleich Wert2 (less or equal)
!Ausdruck
Logische Verneinung von Ausdruck
Ausdruck -a Ausdruck
Logisches UND. Wahr, wenn beide Ausdrücke wahr sind
Ausdruck -o Ausdruck
Logisches ODER. Wahr wenn mindestens einer der beiden Ausdrücke wahr ist
Mit diesen Tests sind so ziemlich alle denkbaren Bedingungsüberprüfungen möglich, die in einem Shellscript notwendig sind.
1.4 Die erweiterte if-else Anweisung
Natürlich bietet die if-Anweisung auch eine Erweiterung zur normalen Form, die sogenannte if-else Anweisung. Es ist also möglich zu schreiben:
if [ Ausdruck ] then Kommandos else Kommandos fi
1.5 Die if-elif-else Anweisung
Um noch einen Schritt weiterzugehen bietet die if-Anweisung sogar ein weiteres if im else, das sogenannte elif, das wieder eine Bedingung überprüft:
if [ Ausdruck ] then Kommandos elif [ Ausdruck ] then Kommandos else Kommandos fi
2. Mehrfachauswahl mit case
Oft kommt es vor, dass eine Variable ausgewertet werden muß und es dabei viele verschiedenen Möglichkeiten gibt, welche Werte diese Variable annehmen kann. Natürlich wäre es mit einer langen if-elif-elif-elif… Anweisung möglich, so etwas zu realisieren, das wäre aber sowohl umständlich, als auch schwer zu lesen. Damit solche Fälle einfacher realisiert werden können, gibt es die Mehrfachauswahl mit case. Der prinzipielle Aufbau einer case-Entscheidung sieht folgendermaßen aus:
case Variable in Muster1) Kommando1 ;; Muster2) Kommando2 ;; Muster3) Kommando3 ;; ... esac
Zu beachten sind zunächst die Klammern, die das Muster abschließen. Das Kommando, das zum jeweiligen Muster passt muß mit zwei Strichpunkten abgeschlossen werden. Statt einem Kommando können nämlich auch mehrere Kommandos, durch Strichpunkt getrennt stehen. Nur die doppelten Strichpunkte machen der Shell klar, dass das Kommando für den bestimmten Fall jetzt fertig ist.
Der Abschluß mit esac ist wieder einfach das Wort case rückwärts geschrieben.