# Ablaufsteuerung
There's more than one way to do it!
– Larry Wall
# If und unless
Bedingte Anweisungen mit if
kennen Sie bereits aus JavaScript, und auch die Syntax unterscheidet sich in Perl nicht allzu sehr. Anweisungen mit if
sind vorprüfende Anweisungen, d. h., bevor der Anweisungsblock überhaupt ausgeführt wird, wird überprüft, ob die angegebene Bedingung erfüllt ist. Diese Bedingung wird in runden Klammern nach if
notiert.
if([Bedingung])
{
[Anweisungsblock]
}
Bedingungen
Als Bedingung können Sie nun die verschiedensten Kombinationen aus logischen und Vergleichsoperatoren notieren. Im Anweisungsblock selbst folgen dann die auszuführenden Anweisungen.
if($passwort == "geheim")
{
print "Passwort korrekt. Sie dürfen weiter.";
}
Dieses Beispiel überprüft, ob der Wert des Skalars $passwort
gleich "geheim"
ist. Ist dies der Fall, wird mit der print
-Anweisung ein Text ausgegeben.
Das Beispiel behandelt nur den Fall einer erfüllten Bedingung. Um auch den Fall zu behandeln, wenn die Bedingung nicht erfüllt ist, notieren Sie nach dem ersten Anweisungsblock das Schlüsselwort else
und einen weiteren Anweisungsblock.
if([Bedingung])
{
[Anweisungsblock für erfüllte Bedingung]
}
else
{
[Anweisungsblock für nicht erfüllte Bedingung]
}
Um nun das Beispiel mit dem Passwort für den Fall zu erweitern, dass $passwort
nicht der Zeichenkette geheim
entspricht, hängen Sie einfach einen else
-Anweisungsblock an, in dem Sie die auszuführenden Anweisungen notieren.
if($passwort == "geheim")
{
print "Passwort korrekt. Sie dürfen weiter.";
}
else
{
print "Passwort falsch. Sie dürfen NICHT weiter.";
}
Nun werden beide Fälle behandelt: die korrekte Eingabe und die falsche Eingabe des Passwortes.
# elsif
Für den Fall der Fälle, dass Sie mehrere if
-Abfragen miteinander verketten möchten, gibt es die spezielle Anweisung elsif
. Die entsprechende Syntax lautet:
if([Bedingung])
{
[Anweisungsblock für erfüllte Bedingung]
}
elsif([Bedingung])
{
[Anweisungsblock für erfüllte Bedingung]
}
else
{
[Anweisungsblock für nicht erfüllte Bedingung]
}
Die Verwendung der elsif
-Anweisung in einem solchen Konstrukt lässt sich beliebig oft wiederholen. Falls die Bedingung nach if
nicht erfüllt ist, wird die Bedingung nach elsif
geprüft. Ist auch diese Bedingung nicht erfüllt, wird schlussendlich der else
-Anweisungsblock ausgeführt.
Gerade dann, wenn Sie mehrere Bedingungen überprüfen müssen, die miteinander verknüpft sind, ist die Verwendung einer if
-elsif
-else
-Anweisung besonders hilfreich.
Ein einfaches Beispiel für eine solche Anweisung ist die Überprüfung eines Skalars auf drei mögliche Werte.
if($zahl = 1)
{
print "Der Wert ist 1";
}
elsif($zahl = 2)
{
print "Der Wert ist 2";
}
else
{
print "Der Wert ist weder 1 noch 2.";
}
# unless
Um zu prüfen, ob eine Bedingung nicht erfüllt wird, können Sie die Bedingung mit !
oder not
umkehren, oder Sie notieren anstelle von if
die Anweisung unless
. Anstelle von true
(wahr) wird dann von der Bedingung false
(unwahr) erwartet.
unless($passwort == "geheim")
{
print "Passwort falsch. Sie dürfen NICHT weiter.";
}
else
{
print "Passwort korrekt. Sie dürfen weiter.";
}
Dieses Beispiel entspricht dem am Anfang des Kapitels stehenden, mit dem Unterschied, dass die beiden Anweisungsblöcke vertauscht sind.
# do-Schleife
Schleifen dienen in Programmen dazu, bestimmte Anweisungen so oft zu wiederholen, solange eine Bedingung erfüllt ist, oder so lange wiederholt zu werden, bis eine Bedingung erfüllt ist. Im ersten Fall werden sie vorprüfende und im zweiten nachprüfende Schleifen genannt.
Zur Gruppe der nachprüfenden Schleife gehört die do
-Schleife. Der Unterschied zwischen den Schleifengruppen besteht im Zeitpunkt der Bedingungsprüfung. Bei vorprüfenden Schleifen wird zuerst die Bedingung geprüft und anschließend der Anweisungsblock ausgeführt. Bei nachprüfenden Schleifen wird erst der Anweisungsblock ausgeführt und anschließend auf die Bedingung geprüft. So wird bei nachprüfenden Schleifen der Anweisungsblock immer mindestens einmal durchlaufen, während es bei vorprüfenden Schleifen passieren kann, dass der Anweisungsblock nie durchlaufen wird.
Die Syntax für eine do
-Schleife sieht folgendermaßen aus:
do {
[Anweisungsblock]
} until([Bedingung]);
Der Anweisungsblock einer do
-Schleife wird also so lange durchlaufen, bis die Bedingung erfüllt ist. Ein Beispiel:
my $i = 0;
do {
print $i;
$i++;
} until($i = 10);
Dieses Beispiel gibt die Zahlen von 0 bis 9 aus, da $i
nach der Ausgabe um 1 erhöht wird. Sobald $i
also den Wert 10 erreicht hat, wird die Schleife beendet.
# Variante mit while
Es ist auch möglich, die Bedingung umzukehren, d. h., dass die Schleife so lange durchlaufen wird, wie die Bedingung erfüllt ist. Die Syntax lautet:
do {
[Anweisungsblock]
} while([Bedingung]);
Das passende Beispiel ist folgendes:
my $i = 0;
do {
print $i;
$i++;
} while($i < 10);
Auch diese Schleife gibt die Zahlen von 0 bis 9 aus. Sobald $i
den Wert 10 erreicht hat, wird die Schleife beendet, da die Bedingung zum Ausführen des Anweisungsblocks »solange $i
kleiner 10 ist« lautet.
# for-Schleife
Die for
-Schleife ist eine vorprüfende Schleife. Der Anweisungsblock einer solchen Schleife wird also nur dann ausgeführt, wenn die Bedingung erfüllt ist. Das Besondere ist jedoch, dass Sie einen Startwert, eine Bedingung und eine Anweisung definieren können, die bei jedem Schleifendurchlauf ausgeführt werden. Eine for
-Schleife ist somit wesentlich flexibler als eine do
-while
- oder do
-until
-Schleife.
for([Startwert]; [Bedingung]; [Anweisung])
{
[Anweisungsblock]
}
Als Startwert können Sie einer Variablen einen Wert zuweisen bzw. sie sogar definieren. Sie besitzt dadurch nur für diese Schleife Gültigkeit. Als Bedingung können Sie wiederum jede erdenkliche Kombination aus logischen Operatoren und Vergleichsoperatoren notieren. Der Erhöhungsschritt ist frei wählbar, wobei im Normalfall der Wert der Variablen um 1 erhöht wird. Ein Beispiel:
for(my $i = 0; $i < 10; $i++)
{
print $i;
}
Dieses Beispiel gibt die Zahlen von 0 bis 9 aus. Bei jedem Schleifendurchlauf wird der Wert von $i
um 1 erhöht ($i++
). Die Schleife wird nur ausgeführt, solange $i
kleiner als 10 ist.
# while-Schleife
Die while
-Schleifen gehören ebenfalls zur Gruppe der vorprüfenden Schleifen. Sie werden also nur dann ausgeführt, wenn die Bedingung erfüllt ist, und beendet, wenn die Bedingung nicht mehr erfüllt ist.
while([Bedingung])
{
[Anweisungsblock]
}
Das durch Verwendung der while
-Schleife geänderte Beispiel lautet so:
my $i = 0;
while($i < 10)
{
print $i;
$i++;
}
Auch dieses Beispiel gibt wieder die Zahlen von 0 bis 9 aus. Die Schleife wird nämlich nur durchlaufen, solange $i
kleiner als 10 ist. Andernfalls wird die Schleife beendet.
# while und Hashes
Eine besondere Form der while
-Schleife gibt es für Hashes. Damit lassen sich Hashes Element für Element durchlaufen und der Schlüssel und der Wert des Elements einzelnen ausgeben. Sie machen sich dabei die Methode each
zunutze.
Die each
-Methode traversiert alle Elemente eines Hashs und gibt den Schlüssel und den Wert des Elements zurück. Als Parameter erwartet die Methode den Hash, der traversiert werden soll.
my %capitols = (Deutschland => "Berlin",
Frankreich => "Paris",
England => "London",
Spanien => "Madrid");
my $key;
my $value;
while(($key,$value) = each(%capitols))
{
print "Die Hauptstadt von $key ist $value";
}
Dieses Beispiel würde die folgende Ausgabe produzieren:
Die Hauptstadt von Frankreich ist Paris
Die Hauptstadt von Deutschland ist Berlin
Die Hauptstadt von England ist London
Die Hauptstadt von Spanien ist Madrid
Dies ist also eine sehr bequeme Methode, alle Elemente eines Hashs zu ermitteln und zu verarbeiten. Natürlich sind die Möglichkeiten nicht nur auf das Ausgeben der Schlüssel und Werte beschränkt.
# foreach-Schleife
Die foreach
-Schleife hat eine ähnliche Aufgabe wie die spezielle Variante der while
-Schleife mit each
, mit dem Unterschied, dass sie für Listen gedacht ist. Auch die foreach
-Schleife ist eine vorprüfende Schleife, und als Bedingung wird eine Liste angegeben. Nacheinander wird jedes Element der Liste in der Schleife verfügbar gemacht. Sobald alle Elemente der Liste abgearbeitet wurden, wird die Schleife beendet.
foreach([Bedingung])
{
[Anweisungsblock]
}
Den Wert des gerade aktuellen Elements stellt die Schleife im Skalar $_
zur Verfügung.
my @cities = ("Berlin","Hamburg","Bremen","München","Stuttgart","Köln","Frankfurt/Main");
foreach(@cities)
{
print $_;
}
Die Ausgabe dieses Beispiels lautet:
Berlin
Hamburg
Bremen
München
Stuttgart
Köln
Frankfurt/Main
Wenn Sie den Wert des aktuellen Elements jedoch in einem anderen Skalar als $_
speichern wollen, müssen Sie dies explizit mit angeben.
my @cities = ("Berlin","Hamburg","Bremen","München","Stuttgart","Köln","Frankfurt/Main");
my $city;
foreach $city (@cities)
{
print $city;
}
Die Ausgabe dieses Beispiels entspricht dem vorherigen.
# Spezielle Notation
Besonders interessant ist, dass Perl die zu verwendende Schleife automatisch erkennen kann. Immerhin sind sich die for
- und foreach
-Schleife semantisch sehr ähnlich. Anstatt eine Liste anzugeben, können Sie auch als Bedingung eine Liste definieren. Der Code
for("A".."Z")
{
print $_;
}
würde die folgende Ausgabe erzeugen:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Sie könnten auch anstelle der Buchstaben von A bis Z einen Zahlenbereich angeben.
for(1..5)
{
print "$_. Durchlauf";
}
Dies ergibt die folgende Ausgabe:
1. Durchlauf
2. Durchlauf
3. Durchlauf
4. Durchlauf
5. Durchlauf
# Schleifensteuerung
Mit speziellen Anweisungen ist es möglich, das Verhalten einer Schleife direkt zu beeinflussen.
# Durchlauf wiederholen
Mit der Anweisung redo
können Sie einen Schleifendurchlauf wiederholen, ohne dass die Bedingung erneut überprüft wird.
my $i = 0;
while($i < 10)
{
$i++;
if($i == 3) { redo };
print "$i<br>";
}
Dieses Beispiel gibt die Zahlen von 1 bis 10 aus, mit Ausnahme der Zahl 3. Sie wird nicht übergeben, da vor der print
-Anweisung eine Abfrage stattfindet. Die Anweisung überprüft, ob $i
den Wert 3 hat, und wiederholt in diesem Fall die Schleife.
# Schleife abbrechen
Mit der Anweisung last
können Sie eine Schleife sofort abbrechen, ohne Rücksicht auf die Bedingung.
my $i = 0;
while(1)
{
$i++;
print "$i<br>";
if($i == 5) { last };
}
Dieses Beispiel ist übrigens eine klassische Endlosschleife, da die Bedingung 1
immer erfüllt ist. Diese Schleife würde also den Bildschirm mit Nullen füllen, bis entweder das Perl-Script durch den Server gestoppt wird oder der Benutzer die Ausführung des Scripts abbricht, wenn nicht die Anweisung
if($i == 5) { last };
notiert worden wäre. Diese führt nämlich dazu, dass die Schleife abgebrochen wird, sobald $i
den Wert 5 hat.
# Durchlauf überspringen
Den aktuellen Durchlauf können Sie mit der Anweisung next
überspringen.
my $i = 0;
for(my $i = 0; $i < 10; $i++)
{
if($i == 3) { next };
print "$i<br>";
}
Dieses Beispiel gibt die Zahlen von 0 bis 9 aus, überspringt dabei aber die Zahl 3.
# Zusammenfassung
- Es gibt vorprüfende und nachprüfende Schleifen.
- Bei vorprüfenden Schleifen kann es vorkommen, dass der Anweisungsblock gar nicht ausgeführt wird.
- Bei nachprüfenden Schleifen wird der Anweisungsblock mindestens einmal durchlaufen.
- Mit den Anweisungen
next
,redo
undlast
lassen sich die Schleifen explizit steuern.
# Fragen und Übungen
- Worin bestehen die beiden Unterschiede zwischen der
for
-Schleife und derdo
-until
-Schleife? - Was ist das Besondere an der
for
-Schleife? - Wofür wird die
foreach
-Schleife verwendet? - Schreiben Sie ein vollständiges Perl-Script, das den Schlüsselnamen und Wert eines Hashs in einer HTML-Tabelle ausgibt!