In der letzten Ausgabe haben Sie die if-Konstruktion und das Vergleichsprogramm test kennengelernt. Damit war es uns erstmals möglich, den Programmablauf von äußeren Umständen abhängig zu machen; je nach Situation wurden andere Befehle ausgeführt. Die Bash kennt noch weitere Kontrollstrukturen, die insbesondere bei umfangreichen Vergleichen und zum mehrfachen Aufruf einzelner Befehle benötigt werden (Schleifen).
Parametererkennung
Beginnen wollen wir mit einem kleinen Skript. Wie fast jedes andere Linux-Programm soll unser Skript mittels Parameter -h oder --help eine kurze Erklärung der erlaubten Optionen ausgeben und sich dann beenden. Dazu verwenden wir ein if-Konstrukt, wie Sie es im letzten Teil kennen gelernt haben:
#!/bin/bash if [ "$1" = "-h" -o "$1" = "--help" ]; then echo "Aufruf:" echo " $0 [-h|--help]" echo "Parameter:" echo " -h, --help: Kurzerklärung" fi
Relativ umständlich und unübersichtlich wird es, wenn wir mehrere Parameter überprüfen müssen und zudem Groß-/Kleinschreibung ignorieren wollen:
#!/bin/bash
if [ "$1" = "-h" -o "$1" = "-H" -o -z "${1#--[hH][eE][lL][pP]}" ]; then
echo "-h"
elif [ "$1" = "-v" -o "$1" = "-V" ]; then
echo "-v"
elif [ "$1" = "-q" -o "$1" = "-Q" ]; then
echo "-q"
fi
Der Test auf --help in der zweiten Zeile ist erklärungsbedürftig. Um nicht auf --help in allen Varianten der Groß-/Kleinschreibung zu prüfen, verwenden wir die Mustererkennung aus Teil 3 unsers Kurses. Mit ${1#--[hH][eE][lL][pP]} durchsuchen wir die Variable $1 nach einem String, der mit einem Doppel-Minus beginnt und dann ein großes oder kleines H, großes oder kleines E und so weiter enthält. Ist in $1 tatsächlich --help in einer beliebigen Groß-/Klein-Kombination enthalten, wird es entfernt – übrig bleibt eine leere Zeichenkette. Hier kommt der Test-Parameter -z ins Spiel: Er liefert dann einen wahren Wert, wenn die dahinter stehende Zeichenkette leer ist – also eine Version von --help gefunden wurde. Worte, die nur mit --help beginnen (zum Beispiel --helper) fallen beim Test durch, weil die Endung übrig bleiben würde.
Vereinfachung mit <C>case<C>
Wie am vorhergehenden Beispiel zu sehen: Umfangreiche Parameter-Prüfungen kann man so kaum durchführen. Vereinfachung tut Not. Das Vorgehen beim Parameter-Vergleich ist stets gleich: Wir prüfen in jedem Fall, ob der erste Parameter eine bestimmte Gegebenheit erfüllt. Für solche Reihenvergleiche gibt es die case-Konstruktion:
#!/bin/bash
case $1 in
-h|-H|--[hH][eE][lL][pP])
echo "-h"
;;
-v|-V)
echo "-v"
;;
-q|-Q)
echo "-q"
;;
esac
Das case-Konstrukt besteht aus den umschließenden Schlüsselworten case und esac (wie das schließende fi zu if ist auch esac die Umkehrung der Buchstaben aus case), einer Zeichenkette (hier $1), die überprüft wird, und den einzelnen Blöcken mit den jeweiligen Fällen. Diese Blöcke beginnen mit dem Muster, das von einer schließenden runden Klammer begrenzt wird, und enden mit einem Doppel-Semikolon – dazwischen stehen die Anweisungen, die für den jeweiligen Fall ausgeführt werden sollen.
In unserem Beispiel haben wir drei unterschiedliche Fälle, -h, -v und -q. Das Muster des ersten Falls besteht aus drei Teilen, von denen eines wahr sein muss. Die Muster selbst sind nahezu identisch mit denen aus unserem if-Konstrukt, allerdings deutlich übersichtlicher.
Neben den eckigen Klammern, mit denen man erlaubte Zeichen oder Zeichenbereiche angeben kann, gibt es noch die Platzhalter (Wildcards) ? für ein beliebiges Zeichen und * für beliebige Zeichenfolgen. Damit lassen sich zum Beispiel die verschiedenen Netzwerk-Devices voneinander unterscheiden:
case $device in
eth*)
echo "Ethernet"
;;
ppp*)
echo "Modem"
;;
ippp*)
echo "ISDN"
;;
lo)
echo "Loopback"
;;
*)
echo "Unbekannt"
esac
Das letzte Muster, "*", trifft auf jede beliebige Zeichenkette zu – weshalb dieses case-Konstrukt eigentlich stets "Unbekannt" liefern müsste. Doch die Fälle werden von oben nach unten abgearbeitet, und es wird nur der erste ausgeführt, der passt: Alle weiteren werden ignoriert. So wird bei "ppp0" nur "Modem" ausgegeben, nicht aber "Unbekannt". Das Skript wird dann nach Abarbeitung des Falls hinter dem esac-Schlüsselwort fortgesetzt.



