Unterabschnitte


Schleifen

Es gibt vier Schleifentypen in der Shell: for, while, until, und select.

Alle Typen können vorzeitig mit break verlassen werden, oder mit continue kann mit dem nächsten Durchlauf beziehungsweise dem nächsten Prüfen der Bedingung fortgefahren werden (es wird also nur der Rest des Schleifenrumpfes übersprungen).

Wenn break oder continue ohne Argument angegeben werden, dann betreffen sie nur die innerste umgebende Schleife. Man kann sie aber auch mit einem positiven Argument aufrufen; dann betreffen sie entsprechend soviele der innersten umgebenden Schleifen.


for-Schleife

Eine for-Schleife unterscheidet sich von ähnlichen Schleifen in anderen Sprachen dadurch, daß sie nicht Anfangs- und Endwerte von Schleifenzählern beziehungsweise irgendwelche Abbruchbedingungen bekommt, und dann die Zwischenwerte selbst berechnet, sondern vielmehr muß man ihr alle Werte geben, für die die Schleife ausgeführt werden soll. Also nicht für Werte von i von 1 bis 5 in Einserschritten, sondern stattdessen für die Werte ("1", "2", "3", "4", und "5").

Dabei sind die angegebenen Werte in Wirklichkeit wieder gar keine Zahlen, sondern nur Strings.

Damit ist die for-Schleife keine Zählschleife, wie man vielleicht erwartet hätte, sondern eine Schleife über eine Liste von Strings.

Eine reine Zählschleife kann man dagegen mit while (siehe while-Schleife) und beispielsweise expr (Numerik light mit expr) bauen.



Die Struktur einer solchen Schleife sieht so aus:
for name in ersterwert zweiterwert dritterwert...
do
# Verwenden von $name
# Beim 1. Durchlauf hat $name den Wert "ersterwert",
# beim 2. Durchlauf hat $name den Wert "zweiterwert", ...
done

Beispiel 13   Anzeige von 4 Dateinamen, und Löschen dieser Dateien:
for f in a.f77 b.cpp a.o b.cpp
do
echo Ich lösche die Datei $f
rm $f
done



Man kann eine for-Schleife auch einzeilig schreiben. Das ist besonders dann interessant, wenn man nicht in einem Skript arbeitet, sondern die Schleife interaktiv eingibt. Die obige Schleife würde so aussehen:
for f in a.f77 b.cpp a.o b.cpp; do echo Ich lösche die Datei $f; rm $f; done
Man muß dabei allerdings an einigen Stellen mit einem Semikolon (;) der Shell einen Hinweis geben, wo die Liste der Schleifenwerte beziehungsweise die Liste der Argumente eines Kommandos endet.



Wenn man das Schlüsselwort in und die Liste der Schleifenwerte wegläßt, dann läuft die Schleife über alle Werte in $* (siehe Vordefinierte und spezielle Variablen, shift, set).

Die Schleife:
for name
do
# Verwenden von $name
done
ist also identisch mit dieser Version:
for name in $*
do
# Verwenden von $name
done



Bevor die Schleife ausgeführt wird, wird in der Liste der Schleifenwerte eine Dateinamenexpansion durchgeführt. Dies ist sehr praktisch, wenn man eine Schleife über bestimmte Dateien laufen lassen will.

Beispiel 14   Löschen aller Dateien mit der Endung .bak im aktuellen Verzeichnis:
for f in *.bak
do
rm $f
done

Wenn man jetzt nicht nur die Dateien eines Verzeichnisses anfassen will, sondern auch in allen Unterverzeichnissen, dann muß dafür wie immer find herhalten.

Beispiel 15   Löschen aller Dateien mit der Endung .bak im aktuellen Verzeichnis und allen darunter liegenden Verzeichnissen:
for f in `find ~/aweho000411 -name "*.bak"`;
do
rm $f
done


while-Schleife

Eine while-Schleife führt die Anweisungen im Schleifenrumpf solange aus, wie ein Test des angegebenen Ausdrucks (vor Eintritt in den Schleifenrumpf) 0, also false ergibt.

Als Bedingung kann man jedes Kommando nehmen; häufig wird dafür test beziehungsweise [ ... ] verwendet (siehe test-Ausdrücke, true, false).

Die Struktur einer solchen Schleife sieht so aus:
while Ausdruck
do
# Schleifenrumpf
Kommando1
...
done

Zusammen mit expr (siehe Numerik light mit expr) kann man damit auch echte Zählschleifen bauen.

Beispiel 16   Das folgende Beispiel gibt die Zahlen von -1 bis 10 aus:
i=-1
while [ $i -le 10 ]
do
echo $i
i=`expr $i + 1`
done

Beispiel 17   Statt expr kann man wahlweise auch bc nehmen. Die Schleife würde dann so aussehen:
i=-1
while [ `echo $i "<"= 10 | bc` != 0 ]
do
echo $i
i=`echo $i + 1 | bc`
done

Beispiel 18   Eine letzte Variante derselben Schleife nutzt weder expr noch bc, sondern die interne Arithmetik der bash. Dieses Skript ist deshalb nur mit der bash lauffähig!
#!/bin/bash
# nur BASH!!!
i=-1
while [ $i -le 10 ]
do
echo $i
i=$[ $i + 1 ] # oder: i=$(($i+1)) oder : $((i=$i+1))
done

Die einzeilige Version sieht so aus:
while Ausdruck; do Kommando1;...; done


until-Schleife

Die until-Schleife entspricht der while-Schleife; im Gegensatz dazu wird die Bedingung aber negiert verwendet (die Schleife läuft nicht -wie bei while- solange die Bedingung true (0) liefert, sondern vielmehr solange sie NICHT true (0) liefert).

Siehe while-Schleife.

Die Struktur einer until-Schleife sieht so aus:
until Ausdruck
do
# Schleifenrumpf
Kommando1
...
done

Die einzeilige Version sieht so aus:
until Ausdruck; do Kommando1;...; done


select-Schleife

Mit select kann man schnell und einfach ein kleines Menü zaubern. Sozusagen fast food für die Shellprogrammierung.

select zeigt in einer Endlosschleife eine Auswahl für den Benutzer an. Die Schleife verläßt man bei Bedarf mit break im Skript.

Die Struktur ähnelt sehr einer for-Schleife:
for name in ersteauswahl zweiteauswahl dritteauswahl...
do
# In $name steht der Text der Auswahl
done

Beispiel 19   Es werden ein paar (nicht sehr intelligente) Auswahlmöglichkeiten angeboten. Die Schleife wird verlassen, wenn der Benutzer eine 6 (für ende) eingibt:
#!/bin/sh
echo soll alles eventuell nicht formatiert werden\?
select name in ja nein "weiß nicht" "keine Hilfe!" "vielleicht" "ende"
do
    echo ausgewählt wurde $name
    if [ "$name" = ende ]
    then
        break
    fi
done
echo fertig
Ein Beispieldialog könnte so aussehen, wenn der Benutzer nacheinander die Werte 1, 4, und 6 eingibt:
soll alles eventuell nicht formatiert werden?
1) ja 3) weiß nicht 5) vielleicht
2) nein 4) keine Hilfe! 6) ende
#? 1
ausgewählt wurde ja
1) ja 3) weiß nicht 5) vielleicht
2) nein 4) keine Hilfe! 6) ende
#? 4
ausgewählt wurde keine Hilfe!
1) ja 3) weiß nicht 5) vielleicht
2) nein 4) keine Hilfe! 6) ende
#? 6
ausgewählt wurde ende
fertig

AnyWare@Wachtler.de