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.
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
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.
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.
for f in `find ~/aweho000411 -name "*.bak"`;
do
rm $f
done
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.
i=-1
while [ $i -le 10 ]
do
echo $i
i=`expr $i + 1`
done
i=-1
while [ `echo $i "<"= 10 | bc` != 0 ]
do
echo $i
i=`echo $i + 1 | bc`
done
#!/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
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
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
#!/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 fertigEin 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