TOC PREV Übungen NEXT INDEX

3 Listen und Arrays

Wenn wir Skalare als den »Singular« in Perl betrachten (wie zu Beginn von Kapitel 2 beschrieben), so wird der »Plural« durch Listen und Arrays dargestellt.

Eine Liste ist eine geordnete Ansammlung von skalaren Werten. Ein Array ist eine Variable, die eine Liste enthält. In Perl werden diese zwei Begriffe oft benutzt, als seien sie gegeneinander austauschbar. Um genau zu sein, handelt es sich bei der Liste jedoch um die Daten und beim Array um die Variable. So können Sie einen Listenwert haben, der sich nicht in einem Array befindet; eine Arrayvariable enthält jedoch immer eine Liste (auch wenn diese Liste leer sein kann). Abbildung 3-1 zeigt eine Liste, die sich in einer Arrayvariablen befinden kann, aber nicht muß.
Abbildung 3-1: Eine Liste mit fünf Elementen

Jedes Element eines Arrays oder einer Liste ist eine für sich stehende skalare Variable, die ihrerseits einen eigenständigen skalaren Wert enthalten kann. Diese Werte geordnet - d. h. sie haben eine bestimmte Reihenfolge vom ersten bis zum letzten Element. Die Elemente eines Arrays oder einer Liste werden durch kleine Integer (ganzzahlige Werte) indiziert. Die Indizierung beginnt mit null1 und wird in Einerschritten hochgezählt; das erste Element eines Arrays oder einer Liste ist also immer das Element Null.

Da jedes Element einen von den anderen unabhängigen skalaren Wert enthalten kann, ist es möglich, daß eine Liste oder ein Array aus Zahlen, Strings, undefinierten Werten oder einer beliebigen Kombination aus skalaren Werten besteht. Wesentlich üblicher ist es jedoch, daß alle Elemente den gleichen Typ besitzen, wie etwa eine Liste von Buchtiteln (nur Strings) oder eine Liste von Kosinus-Werten (nur Zahlen).

Arrays und Listen können eine beliebige Anzahl an Elementen enthalten. Die kleinste hat dabei überhaupt kein Element, die größte füllt Ihren gesamten Hauptspeicher. Auch hier gilt wieder Perls Philosphie der »Grenzenlosigkeit«.

Zugriff auf Arrayelemente

Wenn Sie bereits mit anderen Programmiersprachen vertraut sind, wird es Sie nicht wundern, daß es auch in Perl eine Möglichkeit gibt, ein Array zu indizieren, um ein Element über seinen numerischen Index anzusprechen.

Die Elemente eines Arrays werden mit Hilfe einer Folge von ganzzahligen Werten numeriert. Die Indizierung beginnt bei null und wird für jedes weitere Element um eins erhöht, wie hier:

 $fred[0] = "yabba";
 $fred[1] = "dabba";
 $fred[2] = "duuh";

Der Name des Arrays (in diesem Fall "fred") kommt hierbei aus einem komplett anderen Namensraum als der von Skalaren benutzte; Sie könnten also eine skalare Variable mit dem Namen $fred im gleichen Programm benutzen und Perl würde sie als verschiedene Dinge behandeln, ohne sich verwirren zu lassen.2 (Den Wartungsprogrammierer würde das jedoch schon verwirren. Benennen Sie also nicht alle Variablen mit dem gleichen Namen, bloß weil Ihnen gerade danach ist!)

Sie können ein Arrayelement, wie $fred[2], überall dort3 benutzen, wo auch die Verwendung von skalaren Variablen, wie etwa $fred, möglich ist. Daher können Sie den Wert eines Arrayelements auch mit den gleichen Methoden auslesen oder ändern, die wir bereits im vorigen Kapitel für skalare Variablen benutzt haben:

 print $fred[0];
 $fred[2] = "manamana";
 $fred[1] .= "wasndas";

Als Index kann natürlich jeder beliebige Ausdruck verwendet werden, der einen numerischen Wert zum Ergebnis hat. Ist dies bereits ein ganzzahliger Wert, so wird auf den nächsten darunterliegenden Wert abgerundet:

 $zahl = 2.71828;
 print $fred[$zahl - 1]; # das gleiche wie die Ausgabe von $fred[1]

Weist der Index auf ein Element, das hinter dem Ende eines Arrays liegen würde, wird der entsprechende Wert automatisch als undef angesehen. Dies funktioniert genauso wie mit normalen Skalaren. Sofern Sie einer Variablen keinen Wert zugewiesen haben, ist ihr Wert undef.

 $leer  = $fred[ 142_857 ]; # unbenutztes Arrayelement wird zu undef
 $leer  = $mel; # unbenutzter Skalar $mel wird ebenfalls undef

Besondere Arrayindizes

Wenn Sie versuchen, etwas in einem Arrayelement zu speichern, das hinter dem Ende des Arrays liegt, so wird das Array je nach Bedarf automatisch erweitert. Hierbei gibt es wiederum keine Grenze außer der Größe Ihres Hauptspeichers. Neu erzeugte Elemente werden automatisch mit undef belegt.

 $steine[0]  = 'feuerstein'; # ein Element...
 $steine[1]  = 'schiefer';   # noch eins...
 $steine[2]  = 'lava';       # und noch eins...
 $steine[3]  = 'geroell';    # und noch eins...
 $steine[99] = 'basalt';     # und dazu noch 95 undefinierte
                             # Elemente

Manchmal werden Sie den Index des letzten Elements in einem Array herausfinden wollen. Für das Array von steinen ist das zum Beispiel $#steine.4 Dies ist jedoch nicht das gleiche wie die Anzahl der Elemente, da es auch ein Element mit dem Index Null gibt. Wie Sie im untenstehenden Beispiel sehen können, ist es sogar möglich, diesem Element einen Wert zuzuweisen und so die Größe eines Arrays zu ändern. In der Praxis kommt dies jedoch eher selten vor.5

 $ende = $#steine; # 99, der Index des letzten Elements
 $anzahl_der_steine = $ende + 1;  # in Ordnung, aber wir werden
                                  # später eine bessere Möglichkeit
                                  # kennenlernen
 $#steine = 2;                    # alle Steine nach 'lava'
                                  # vergessen
 $#steine = 99;                   # 97 undefinierte Elemente (die
                                  # vergessenen Steine sind für immer
                                  # verschwunden)
 $steine[ $#steine ] =            # der letzte Stein
 'ein harter Brocken';

Die Benutzung des Wertes von $#name aus dem letzten Beispiel kommt so oft vor, daß Larry sich hierfür eine Abkürzung ausgedacht hat: negative Arrayindizes zählen rückwärts vom Ende des Arrays nach vorn. Denken Sie jedoch nicht, daß diese Indizes beim Erreichen des Anfangs wieder am Ende anfangen. Wenn Sie ein Array mit drei Elementen haben, so sind die drei gültigen negativen Indizes 1 (das letzte Element), 2 (das mittlere Element) und 3 (das erste Element). Im wahren Leben scheint aber jeder nur den negativen Index 1 zu benutzen.

 $steine[ -1 ]   = 'ein harter Brocken'; # eine einfachere Methode, 
                                         # das Obenstehende zu sagen
 $totes_gestein  = $steine[-100];        # benutzt 'feuerstein'
 $steine[ -200 ] = 'kristall';           # schwerer Fehler!

Literale Darstellung

Die literale Darstellung einer Liste oder ein Listenliteral (also die Art, auf die eine Liste im Quellcode Ihres Programms dargestellt wird) ist eine Liste von durch Kommata getrennten Werten, die von runden Klammern umschlossen werden. Diese Werte stellen die einzelnen Elemente Ihrer Liste dar. Zum Beispiel:

 (1, 2, 3)      # eine Liste mit den drei Werten 1, 2, und 3
 (1, 2, 3,)     # die gleichen drei Werte (das Komma am Ende wird
                # ignoriert)
 ("Fred", 4.5)  # zwei Werte: "Fred" und 4,5
 (  )             # eine leere Liste - keine Elemente
 (1..100)       # eine Liste von 100 ganzen Zahlen

In der letzten Zeile wird der Bereichs-Operator .. benutzt, den wir hier zum ersten Mal sehen. Dieser Operator erzeugt eine Liste von Werten, indem er in Einerschritten vom linken bis zum rechten Skalar hochzählt. Zum Beispiel:

 (1..5)            # das gleiche wie (1, 2, 3, 4, 5)
 (1.7..5.7)        # das gleiche - beide Werte werden abgerundet
 (5..1)            # leere Liste - .. funktioniert nur "bergauf"
 (0, 2..6, 10, 12) # das gleiche wie (0, 2, 3, 4, 5, 6, 10, 12)
 ($a..$b)          # Bereich, der durch die gegenwärtigen Werte von 
                   # $a und $b definiert wird.
 (0..$#steine)     # die Indizes des Arrays steine aus dem vorigen
                     Abschnitt

Wie Sie an den letzten zwei Punkten sehen können, müssen die Elemente eines Arrays nicht unbedingt konstant sein - vielmehr kann es sich auch um Ausdrücke handeln, die bei jeder Benutzung des Literals neu ausgewertet werden.

 ($a, 17)           # zwei Werte: der gegenwärtige Wert von $a und 17
 ($b + $c, $d + $e) # zwei Werte

Eine Liste darf natürlich jede beliebige Art von skalaren Werten enthalten, wie diese Liste mit Strings:

 ("Fred", "Barney", "Betty", "Wilma", "Dino")

Die Schreibweise mit qw// abkürzen

Es hat sich gezeigt, daß Listen mit einfachen Wörtern (wie im vorigen Beispiel) in Perl-Programmen immer wieder gebraucht werden. Die Abkürzung qw erleichtert Ihnen das Erstellen, da sich die Eingabe von zusätzlichen Anführungszeichen erübrigt:

 qw/ Fred Barney Betty Wilma Dino / # das gleiche wie oben, 
                                    # aber mit weniger Tipperei

qw steht für »quoted words« (Wörter in einfachen Anführungszeichen) oder »quoted by whitespace« (durch Whitespace-Zeichen getrennte Wörter), je nachdem, wen Sie fragen. Wie dem auch sei, Perl behandelt diese Elemente, als stünden sie in einfachen Anführungszeichen. Die Whitespace-Zeichen (wie z. B. Leerzeichen, Tabulatoren und das Newline-Zeichen) werden verworfen, und was übrigbleibt, wird zu einer Liste von Elementen. Da Whitespace-Zeichen verworfen werden, können wir das Obenstehende auch noch auf eine andere (wenn auch nicht so gebräuchliche) Art schreiben:

 qw/Fred
   Barney     Betty
 Wilma Dino/   # das gleiche wie oben, aber mit ziemlich 
               # seltsamen Whitespace-Zeichen

Da qw anstelle von Anführungszeichen benutzt wird (»Quoting«), können Sie innerhalb einer solchen Liste keine Kommentare benutzen.

In den vorigen zwei Beispielen haben wir Schrägstriche als Trennzeichen verwendet; Perl erlaubt jedoch die Benutzung eines beliebigen Interpunktionszeichens. Hier sehen Sie einige der häufigsten:

 qw! Fred Barney Betty Wilma Dino !
 qw# Fred Barney Betty Wilma Dino #   # Doppelkreuz, wie bei
                                      # Kommentaren!
 qw( Fred Barney Betty Wilma Dino )
 qw{ Fred Barney Betty Wilma Dino }
 qw[ Fred Barney Betty Wilma Dino ]
 qw< Fred Barney Betty Wilma Dino >

Wie die letzten vier Beispiele zeigen, können sich die Trennzeichen voneinander unterscheiden. Ist das öffnende Trennzeichen etwa das »linke« Zeichen eines Paares (z. B. bei Klammern), so ist das korrekte Trennzeichen zum Schließen das dazugehörige »rechte« Zeichen. Andere Trennzeichen benutzen das gleiche Zeichen zum Öffnen und zum Schließen.

Wenn Sie das schließende Trennzeichen innerhalb der Liste als Teil eines Strings benötigen, so haben Sie wahrscheinlich das falsche Trennzeichen gewählt. Aber selbst wenn Sie das Trennzeichen nicht austauschen können oder wollen, ist es möglich, das Zeichen mit einem Backslash zu »entkoppeln«:

 qw! Yahoo\! Google Excite Lycos ! # Yahoo! als Element verwenden

Wie bei einem String in einfachen Anführungszeichen müssen Sie für die Verwendung eines literalen Backslashs diesen mit einem weiteren Backslash schützen (\\).

Obwohl das Motto von Perl »There's More Than One Way To Do It« (Es gibt mehr als eine Möglichkeit, eine Sache zu tun) lautet, fragen Sie sich vermutlich, wozu jemand diese ganzen verschiedenen Möglichkeiten überhaupt braucht. Wir werden später sehen, daß es auch noch andere Quoting-Arten gibt, bei denen Perl nach denselben Regeln vorgeht. Bei vielen von ihnen kann sich diese Vielfalt als nützlich erweisen. Aber selbst hier ist das schon der Fall, etwa, wenn Sie eine Liste von Unix-Dateinamen brauchen:

 qw{
   /usr/dict/words
   /home/rootbeer/.ichsags_english
 }

Diese Liste wäre sehr schwer zu lesen, zu schreiben und zu pflegen, wenn wir nur den Schrägstrich als Trennzeichen zur Verfügung hätten.

Listenzuweisung

Ganz ähnlich wie bei der Zuweisung von skalaren Werten können auch Listen bestimmten Variablen zugewiesen werden.

 ($fred, $barney, $dino) = ("Feuerstein", "Geroellheimer", undef);

Alle drei Variablen in der Liste auf der linken Seite erhalten neue Werte, als hätten wir drei einzelne Zuweisungen vorgenommen. Da die Liste erzeugt wird, bevor die Zuweisung beginnt, ist es leicht, in Perl die Werte zweier Variablen miteinander zu vertauschen:6

 ($fred, $barney) = ($barney, $fred); # diese zwei Werte vertauschen
 ($betty[0], $betty[1]) = ($betty[1], $betty[0]);

Was passiert aber nun, wenn die Anzahl der Variablen (links vom Gleichheitszeichen) und die Anzahl der Werte (auf der rechten Seite) unterschiedlich groß sind? Zusätzliche Werte werden bei der Listenzuweisung stillschweigend ignoriert. Perl geht davon aus, daß Sie ihm mitteilen, wo die Werte gespeichert werden sollen. Gibt es andererseits zu viele Variablen, wird den überflüssigen Variablen undef zugewiesen.7

 ($fred, $barney) = qw< Feuerstein Geroellheimer Schiefer Granit >;
                                            # zwei Werte ignoriert
 ($wilma, $dino) = qw[Feuerstein];          # $dino erhält undef

Nachdem wir nun wissen, wie die Listenzuweisung funktioniert, könnten wir mit einer Codezeile wie dieser ein Array aus Strings erzeugen:8

 ($steine[0], $steine[1], $steine[2]) = qw/Talcum Feldspat Quarz/;

Wollen Sie sich nun auf ein komplettes Array beziehen, so gibt es dafür noch eine bessere Möglichkeit - stellen Sie dem Namen des Arrays einfach ein at-Zeichen (@) voran, und lassen Sie die Index-Klammern weg. Als Eselsbrücke können Sie dies auch als »alle« lesen; @steine liest sich also wie »alle Steine«.9

 @steine     = qw/ Feuerstein Schiefer Lava /;
 @winzig     = (  );                     	# eine leere Liste
 @riesig     = 1..1e5;                  	# eine Liste mit
                                        	# 100.000 Elementen
 @zeug       = (@riesig, undef, @riesig); 	# eine Liste mit
                                       	# 200.001 Elementen
 $dino       = "Granit";
 @steinbruch = (@steine, "Kies", @winzig, $dino);

Die letzte Zuweisung füllt @steinbruch mit einer Liste aus fünf Elementen (Feuerstein, Schiefer, Lava, Kies, Granit), da @winzig keine Elemente enthält. (Um genau zu sein, wird der Liste kein undef hinzugefügt, es sei denn, wir machen das explizit, wie vorher mit @zeug.) Der Name eines Arrays wird bei dieser Art der Zuweisung durch die enthaltenen Elemente ersetzt. Da Arrays nur skalare Werte enthalten können, kann ein Array selbst nicht als Listenelement benutzt werden.10

Der Wert einer Arrayvariablen, der noch nichts zugewiesen wurde ist ( ), die leere Liste. Ähnlich wie neue, leere Skalare zu Beginn undef enthalten, enthalten leere Arrays eine leere Liste.

Auch wenn Sie ein Array in ein anderes kopieren, handelt es sich noch um eine Listenzuweisung. Die Listen sind nur in den Arrays gespeichert. Zum Beispiel:

 @kopie = @steinbruch; # die Liste im Array @steinbruch ins Array
                       # @kopie kopieren

pop und push

Sie könnten neue Werte am Ende eines Arrays einfügen, indem Sie diese einfach in Elementen mit neueren, größeren Indizes speichern. Echte Perl-Programmierer benutzen aber sowieso keine Indizes.11 In den folgenden Abschnitten werden wir Ihnen daher ein paar Methoden zeigen, mit Arrays zu arbeiten, ohne dabei Indizes zu verwenden.

Häufig werden Arrays benutzt, um Informationen in »Stapeln« (Stacks) zu verwalten, bei denen die Werte auf der rechten Seite der Liste hinzugefügt oder entfernt werden. (Hiermit meinen wir die Seite mit den »letzten« Einträgen der Liste bzw. mit den höchsten Indexwerten.) Diese Art von Operationen müssen so oft vorgenommen werden, daß es hierfür spezielle Funktionen gibt.

Der pop-Operator entfernt das letzte Element aus einem Array und gibt es zurück.

 @array = 5..9;
 $fred = pop(@array);  # $fred erhält jetzt 9, @array enthält jetzt 
                       # (5, 6, 7, 8)
 $barney = pop @array; # $barney erhält 8, @array enthält jetzt (5, 6, 7)
 pop @array;           # @array enthält jetzt (5, 6). 
                       # (Die 7 wird verworfen.)

Das letzte Beispiel verwendet pop in einem »leeren Kontext« (void-Kontext). Das ist nur eine andere Art zu sagen, daß der Rückgabewert nicht benutzt wird. Es ist nichts Schlimmes daran, pop auf diese Weise zu benutzen, wenn es das ist, was Sie wollen.

Ist das Array leer, gibt es auch für pop nichts zu tun (da es kein Element zu entfernen gibt); statt eines Elements wird undef zurückgegeben.

Eventuell haben Sie schon gemerkt, daß man pop entweder mit oder ohne runde Klammern benutzen kann. Dies ist eine allgemeingültige Regel in Perl: Solange die Bedeutung einer Anweisung durch das Entfernen der Klammern nicht verändert wird, sind sie optional.12

Die umgekehrte Operation heißt push. Hiermit wird ein Element (oder eine Liste von Elementen) am Ende eines Arrays hinzugefügt:

 push(@array, 0);      # @array enthält nun (5, 6, 0)
 push @array, 8;       # @array enthält nun (5, 6, 0, 8)
 push @array, 1..10;   # @array hat nun zehn neue Elemente
 @andere = qw/ 9 0 2 1 0 /;
 push @array, @others; # @array hat nun weitere fünf Elemente 
                       # (19 insgesamt)

Beachten Sie: Sowohl für push als auch für pop muß das erste Argument eine Arrayvariable sein. Die Verwendung einer literalen Liste für diese Operationen ist sinnlos.

shift und unshift

Die Operatoren push und pop erledigen ihre Arbeit am Ende eines Arrays (bzw. auf der rechten Seite des Arrays oder auf der Seite mit den höchsten Indizes, je nachdem, wie Sie sich ein Array vorstellen). Die Operatoren shift und unshift führen die entsprechenden Aufgaben am »Anfang« des Arrays aus (bzw. auf der »linken« Seite oder auf der Seite mit den niedrigsten Indizes). Hier ein paar Beispiele:

 @array = qw# Dino Fred Barney #;
 $a = shift(@array);      # $a erhält "Dino", @array enthält
                          # jetzt ("Fred", "Barney")
 $b = shift @array;       # $b erhält "Fred", @array enthält nun
                          # ("Barney")
 shift @array;            # @array ist jetzt leer
 $c = shift @array;       # $c erhält undef, @array ist weiterhin
                          # leer
 unshift(@array, 5);      # @array enthält jetzt eine Liste mit
                          # einem Element (5)
 unshift @array, 4;       # @array enthält jetzt (4, 5);
 @andere = 1..3;          # @andere enthält jetzt (1, 2, 3)
 unshift @array, @andere; # @array enthält jetzt (1, 2, 3, 4, 5)

Analog zu pop gibt auch shift den Wert undef zurück, wenn es auf eine leere Arrayvariable angewandt wird.

Interpolation von Arrays in Strings

Wie Skalare können auch Arrayvariablen in einem String in doppelten Anführungszeichen interpoliert werden. Hierbei werden die einzelnen Elemente bei der Interpolation automatisch durch Leerzeichen voneinander getrennt.13

 @steine = qw{ Feuerstein Schiefer Schotter };
 print "Quarz @steine Kalkstein\n";  # Gibt fünf durch Leerzeichen
                                     # voneinander
                                     # getrennte Steine aus.

Vor und nach dem interpolierten Array werden keine zusätzlichen Leerzeichen eingefügt. Wenn Sie welche brauchen, müssen Sie diese selbst einfügen:

 print "Drei Steine: @steine.\n";
 print "In diesen Klammern steht nichts (@empty).\n";

Wenn Sie vergessen, daß Arrays auf diese Art interpoliert werden, werden Sie überrascht sein, wenn Sie eine E-Mail-Adresse in einen String mit doppelten Anführungszeichen schreiben. Aus historischen Gründen wird hierdurch ein fataler Fehler zur Compile-Zeit ausgelöst:14

 $email = "fred@feuerstein.edu";  # FALSCH! Versuch, @feuerstein zu
                                  # interpolieren
 $email = "fred\@feuerstein.edu"; # Richtig
 $email = 'fred@feuerstein.edu';  # Auch eine Möglichkeit

Einzelne Elemente werden durch ihren Wert ersetzt, wie man es erwarten würde:

 @fred = qw(Hello Dolly);
 $y    = 2;
 $x    = "Hier wohnt $fred[1]";    # "Hier wohnt Dolly"
 $x    = "Hier wohnt $fred[$y-1]"; # Das gleiche

Der Index-Ausdruck wird ausgewertet, als stünde er außerhalb des Strings. Es findet vorher keine Variablen-Interpolation statt. Mit anderen Worten: Wenn $y den String "2*4" enthält, reden wir immer noch über das Element mit dem Index 1 und nicht über $fred[7], da "2*4" als Zahl ausgewertet ($y in einem numerischen Ausdruck benutzt) einfach 2 ist.15

Wenn direkt auf eine einfache skalare Variable eine literale eckige Klammer folgen soll, so müssen Sie diese von der davorstehenden Variablen abgrenzen. Ansonsten nimmt Perl an, Sie bezögen sich auf ein Arrayelement. Das geht folgendermaßen:

 @fred = qw(steine essen ist falsch);
 $fred = "richtig";              # Wir wollen sagen: "Dies ist
                                 # richtig[3]"
 print "Dies ist $fred[3]\n";    # Gibt "falsch" aus (Benutzung von
                                 # $fred[3])
 print "Dies ist ${fred}[3]\n";  # Gibt "richtig" aus
                                 # (durch geschweifte Klammern
                                 # geschützt)
 print "Dies ist $fred"."[3]\n"; # auch richtig (separater String)
 print "Dies ist $fred\[3]\n";   # auch richtig (Backslash-Schutz
                                 # verwendet)

Kontrollstrukturen mit foreach

Es ist praktisch, ein Array oder eine Liste »am Stück« zu bearbeiten, daher gibt es in Perl eine Kontrollstruktur, die genau für diesen Zweck gedacht ist. Die foreach-Schleife geht eine Liste (ein Array) Element für Element durch. Bei jeder Iteration (jedem Schleifendurchlauf) wird der angegebene Code für jedes Element jeweils einmal ausgeführt.

 foreach $stein (qw/ Feuerstein Schiefer Lava /) {
   print "$stein ist ein Stein.\n";      # Gibt die Namen von drei
                                         # Steinen aus
 }

Die Kontrollvariable (in diesem Beispiel $stein) nimmt hierbei für jede Iteration einen neuen Wert an. Beim ersten Durchlauf ist dies "Feuerstein" beim dritten Mal "Lava".

Hierbei enthält die Kontrollvariable keine Kopie des Listenelements, sondern das Element selbst. Das heißt, wenn Sie die Kontrollvariable innerhalb der Schleife ändern, so ändern Sie auch das Element selbst, wie im folgenden Code-Fragment gezeigt. Dieses Verhalten ist nützlich und wird offiziell unterstützt, aber es könnte Sie überraschen, wenn Sie nicht damit rechnen.

 @steine = qw/ Feuerstein Schiefer Lava /;
 foreach $stein (@steine) {
   $stein = "\t$stein";  # Vor jedes Element in @steine einen
                         # Tabulator schreiben
   $stein .= "\n";       # Hinter jedem Element ein Newline-Zeichen
                         # einfügen
 }
 print "Die Steine sind:\n", @steine; 
                         # Alle Elemente sind nun eingerückt und
                         # stehen jeweils auf einer eigenen Zeile

Welchen Wert enthält die Kontrollvariable, wenn die Schleife beendet ist? Denselben, den sie hatte, bevor die Schleife gestartet wurde. Der Wert der Kontrollvariablen einer foreach-Schleife wird von Perl automatisch gespeichert und wiederhergestellt. Während die Schleife läuft, gibt es keine Möglichkeit, auf den gespeicherten Wert zuzugreifen. Am Ende der Schleife hat die Kontrollvariable daher den gleichen Wert wie vorher beziehungsweise undef, wenn vorher kein Wert zugewiesen wurde. Wenn Sie Ihre Kontrollvariable also $stein nennen wollen, brauchen Sie sich keine Sorgen zu machen, ob Sie den Namen vielleicht schon für eine andere Variable benutzt haben.16

Die beliebteste Standardvariable in Perl: $_

Wenn Sie am Anfang der foreach-Schleife die Kontrollvariable weglassen, benutzt Perl statt dessen seine beliebteste Standardvariable, $_. Diese verhält sich (meistens) wie jede andere skalare Variable, wenn wir einmal von ihrem ungewöhnlichen Namen absehen. Zum Beispiel:

 foreach (1..10) {  # Standardmäßige Benutzung von $_
   print "Ich kann bis $_ zaehlen.\n";
 }

Dies ist bei weitem nicht die einzige Standardvariable in Perl, auf jeden Fall aber die am häufigsten benutzte. Wir werden noch viele Fälle sehen, in denen Perl automatisch die Variable $_ benutzt, sofern Sie keine andere angegeben haben. Hierdurch erspart Perl dem Programmierer die harte Arbeit, sich einen neuen Variablennamen auszudenken und diesen einzugeben. Um Sie nicht noch länger auf die Folter zu spannen: Einer dieser Fälle ist die Verwendung der Funktion print, die ebenfalls auf $_ zurückgreift, wenn kein anderes Argument angegeben wurde:

 $_ = "Yabba dabba duuuh\n";
 print;  # standardmäßige Benutzung von $_

Der reverse-Operator

Der reverse-Operator übernimmt eine Werteliste (die auch aus einem Array kommen kann) und gibt sie in umgekehrter Reihenfolge wieder zurück. Wenn Sie also enttäuscht sind, daß der Bereichsoperator (..) nur »aufwärts« funktioniert - hier ist der Ausweg:

 @fred = 6..10;
 @barney = reverse(@fred); # ergibt 10, 9, 8, 7, 6
 @wilma  = reverse 6..10;  # ergibt das gleiche, aber ohne
                           # zusätzliches Array
 @fred   = reverse @fred;  # schreibt das Ergebnis ins ursprüngliche
                           # Array zurück

Die letzte Zeile ist beachtenswert, da hier @fred zweimal benutzt wird. Perl berechnet auch hier den zuzuweisenden Wert (auf der rechten Seite), bevor die eigentliche Zuweisung vorgenommen wird.

Denken Sie daran, daß reverse eine Liste in umgekehrter Reihenfolge zurückgibt. Hierbei werden die Argumente selbst nicht verändert. Wird also der Rückgabewert nirgendwo zugewiesen, ist diese Funktion nutzlos:

 reverse @fred;         # FALSCH - @fred wird nicht verändert
 @fred = reverse @fred; # schon viel besser

Der sort-Operator

Der sort-Operator übernimmt eine Liste von Werten und sortiert sie nach der intern definierten Zeichen-Reihenfolge. Für Strings im ASCII-Format wäre dies folglich ASCIIbetisch. Sicher, ASCII ist ein seltsames System, in dem alle Großbuchstaben vor allen Kleinbuchstaben kommen und die Zahlen sogar vor allen Buchstaben, und die Interpunktionszeichen - nun ja, die sind hier und da und sonstwo. Aber die Sortierung in ASCII-Ordnung ist ja nur das Standardverhalten; in Kapitel 15, Strings und Sortierfunktionen, werden wir sehen, wie Sie Dinge auf Ihre Art sortieren können:

 @steine   = qw/ Feuerstein Schiefer Schotter Granit /;
 @sortiert = sort(@steine);        # ergibt Feuerstein Granit 
                                   # Schiefer Schotter
 @zurueck  = reverse sort @steine; # von Schotter nach Feuerstein
 @steine   = sort @steine;         # schreibt das sortierte Ergebnis
                                   # zurück in @steine
 @zahlen   = sort 97..102;         # ergibt 100, 101, 102, 97, 98, 99

Wie Sie am letzten Beispiel erkennen können, ergibt der Versuch, Zahlen zu sortieren, als seien sie Strings, nicht unbedingt sinnvolle Ergebnisse. Allerdings muß nach den Standardsortierregeln ein String, der mit 1 beginnt, natürlich vor einem String stehen, der mit 9 beginnt. Und wie bei der Verwendung von reverse wird auf die Argumente selbst kein Einfluß genommen. Wenn Sie ein Array sortieren wollen, müssen Sie das Ergebnis auch wieder in einem Array speichern:

 sort @steine;   	# FALSCH, @steine wird nicht verändert
 @steine = sort @steine; 	# Jetzt haben wir unsere Steinsammlung geordnet

Skalarer Kontext und Listenkontext

Dies ist der wichtigste Abschnitt in diesem Kapitel. Eigentlich ist dies sogar der wichtigste Abschnitt im ganzen Buch. Es wäre nicht einmal übertrieben zu sagen, daß Ihre gesamte Perl-Karriere davon abhängt, ob Sie diesen Abschnitt verstehen. Wenn Sie den Text also bisher nur überflogen haben, ist jetzt der Moment gekommen, wo Sie wirklich aufpassen sollten.

Damit wollen wir natürlich nicht sagen, daß dieser Abschnitt jetzt besonders schwer zu verstehen wäre. Eigentlich handelt es sich um eine einfache Idee: Ein gegebener Ausdruck kann verschiedene Dinge bedeuten, je nachdem, in welchem Zusammenhang er auftaucht. Das sollte für Sie nichts Neues sein; in natürlichen Sprachen passiert das ständig. Zum Beispiel kann das Wort »ausgeben« verschiedene Bedeutungen haben, die davon abhängen, wie es benutzt wird. Die wirkliche Bedeutung können Sie sich erst aus dem Kontext erschließen.

Je nachdem, wo Ihr Ausdruck steht, hat er einen bestimmten Kontext. Wenn Perl Ihre Ausdrücke parst, erwartet es immer entweder einen skalaren Wert oder einen Listenwert.17 Dies nennt man den Kontext eines Ausdrucks.18

 5 + irgendetwas  # Hier muß irgendetwas ein skalarer Wert sein
 sort irgendetwas # Hier muß irgendetwas ein Listenwert sein

Selbst wenn es sich bei irgendetwas um die gleiche Folge von Zeichen handelt, wird sie in einem Fall als Skalar interpretiert, im anderen jedoch als Liste. 19

Ausdrücke geben in Perl immer den ihrem Kontext entsprechenden Wert zurück. Nehmen wir zum Beispiel den »Namen«20 eines Arrays. Im Listenkontext werden die einzelnen Elemente zurückgegeben, im skalaren Kontext jedoch die Anzahl der Elemente:

 @leute    = qw( Fred Barney Betty );
 @sortiert = sort @leute; # Listenkontext Barney, Betty, Fred
 $zahl     = 5 + @leute;  # skalarer Kontext: 5 + 3 ergibt 8

Selbst eine einfache Zuweisung (auf einen skalaren Wert oder eine Liste) kann einen unterschiedlichen Kontext bedeuten:

 @liste = @leute; # eine Liste mit drei Namen
 $n = @leute;     # die Zahl 3

Ziehen Sie jetzt jedoch nicht voreilig den Schluß, ein skalarer Kontext gäbe immer die Anzahl der Elemente zurück. Die meisten Ausdrücke, die eine Liste zurückgeben,21 haben wesentlich interessantere Rückgabewerte.

Ausdrücke, die eine Liste zurückgeben, in skalarem Kontext benutzen

Es gibt eine Menge Ausdrücke, die typischerweise benutzt werden, um eine Liste zu erzeugen. Was bekommen Sie aber, wenn Sie diesen Ausdruck in skalarem Kontext benutzen? Am besten Sie fragen die Person, die sich diese Funktion ausgedacht hat, meistens also Larry. Die vollständige Antwort ist daher auch meistens in der Dokumentation zu finden. Das Lernen von Perl besteht sowieso zu einem großen Teil darin zu verstehen, wie Larry denkt.22 Wenn Sie also denken können wie Larry, wissen Sie auch, wie Perl sich in bestimmten Situationen verhält. Solange Sie jedoch noch dabei sind zu lernen, ist es vermutlich leichter, in der Dokumentation nachzuschlagen.

Manche Ausdrücke haben nicht einmal einen skalaren Kontext. Was würde zum Beispiel sort im skalaren Kontext zurückgeben? Eine Liste müssen Sie nicht erst sortieren, um die Anzahl der Elemente zurückzubekommen. Daher gibt sort in skalarem Kontext auch undef zurück, solange nicht jemand etwas anderes implementiert.

Ein anderes Beispiel ist reverse. Im Listenkontext wird eine umgekehrte Liste zurückgegeben. In skalarem Kontext wird ein umgekehrter String zurückgegeben (beziehungsweise die Umkehrung aller Strings in einer Liste hintereinandergehängt).

 @rueckwaerts = reverse qw/ yabba dabba duuuh /;
    # ergibt duuuh, dabba, yabba
 $rueckwaerts = reverse qw/ yabba dabba duuuh /;
    # ergibt huuudabbadabbay

Anfangs ist es nicht immer offensichtlich, ob ein Ausdruck in skalarem Kontext oder im Listenkontext benutzt wurde. Aber vertrauen Sie uns - es wird Ihnen bald zur zweiten Natur werden.

Hier ein paar Beispiele für die verschiedenen Arten von Kontext zum Anfangen:

 $fred = irgendetwas;               # skalarer Kontext
 @pebbles = irgendetwas;            # Listenkontext
 ($wilma, $betty) = irgendetwas;    # Listenkontext
 ($dino) = irgendetwas;             # immer noch Listenkontext

Lassen Sie sich vom letzten Beispiel nicht täuschen. Hier handelt es sich nicht um einen skalaren Kontext, sondern um einen Listenkontext. Wenn Sie einer Liste etwas zuweisen (unabhängig von der Anzahl der Elemente), geschieht dies automatisch im Listenkontext. Weisen Sie einem Array etwas zu, geschieht dies ebenfalls im Listenkontext.

Hier sehen Sie ein paar andere Ausdrücke, die wir bereits kennen, und der dazugehörige Kontext. Zuerst einige Beispiele, die irgendetwas in skalarem Kontext benutzen.

 $fred    = irgendetwas;
 $fred[3] = irgendetwas;
 123 + irgendetwas
 irgendetwas + 654
 if (irgendetwas)    { ... }
 while (irgendetwas) { ... }
 $fred[irgendetwas] = irgendetwas;

Und hier ein paar, die irgendetwas im Listenkontext benutzen:

 @fred = irgendetwas;
 ($fred, $barney) = irgendetwas;
 ($fred) = irgendetwas;
 push @fred, irgendetwas;
 foreach $fred (irgendetwas) { ... }
 sort irgendetwas;
 @fred = reverse irgendetwas;
 print irgendetwas;

Ausdrücke, die Skalare erzeugen, im Listenkontext benutzen

So herum ist alles ganz einfach: Hat ein Ausdruck normalerweise keinen Listenwert, so wird der skalare Wert automatisch als Liste mit einem Element angesehen:

 @fred   = 6 * 7; # erzeugt eine Liste mit einem Element (42)
 @barney = "Hallo" . ' ' . "Welt";

Eines gibt es jedoch zu beachten:

 @wilma = undef; 	# HOPPLA! erzeugt eine Liste mit einem Element 
                	# (undef), was nicht das gleiche ist wie dies:
 @betty = (  );    	# die korrekte Art, ein Array zu leeren (leere Liste)

Da undef ein skalarer Wert ist, können Sie ein Array nicht leeren, indem Sie ihm undef zuweisen. Der bessere Weg besteht darin, ihm eine leere Liste zuzuweisen.23

Skalaren Kontext erzwingen

Gelegentlich kann es notwendig sein, einen skalaren Kontext zu erzwingen, wo Perl eigentlich eine Liste erwartet. Hierfür gibt es die Funktion scalar. Dies ist keine »echte« Funktion, da sie Perl nur anweist, einen skalaren Kontext zu verwenden.

 @steine = qw( Feuerstein Quarz Jade Obsidian );
 print "Wie viele Steine haben Sie?\n";
 print "Ich habe ", @steine, " Steine!\n";        # FALSCH, gibt die
                                                  # Namen aus
 print "Ich habe ", scalar @steine, " Steine!\n"; # Richtig, ergibt
                                                  # eine Zahl

Seltsamerweise gibt es keine Funktion, die einen Listenkontext erzwingt. Es hat sich gezeigt, daß so etwas einfach nicht gebraucht wird. Vertrauen Sie uns einfach.

<STDIN> im Listenkontext

Ein Operator, der je nach Kontext einen anderen Wert ausgibt, ist uns bereits bekannt: <STDIN>. Wie bereits gesagt wurde, gibt <STDIN> im skalaren Kontext jeweils die folgende Zeile einer Eingabe zurück. Im Listenkontext gibt es alle verbleibenden Zeilen bis zum Dateiende zurück. Jede Zeile wird hierbei als eigenes Listenelement behandelt. Zum Beispiel:

 @zeilen = <STDIN>; # im Listenkontext von Standardeingabe lesen

Kommt die Eingabe aus einer Datei, wird hiermit bis zum Dateiende gelesen. Aber woher soll das Dateiende kommen, wenn die Eingabe von der Tastatur kommt? Auf Unix-Systemen und Unix-verwandten Systemen (inklusive Linux und MacOS X) können Sie normalerweise einfach ControlD24 eingeben, um dem System zu zeigen, daß keine weiteren Eingaben mehr folgen; das spezielle Zeichen sieht Perl hierbei nicht,25 selbst, wenn es auf dem Bildschirm angezeigt werden sollte. Auf DOS/Windows-Systemen benutzen Sie statt dessen Ctrl-Z.26

Gibt die Person, die das Programm ausführt, drei Zeilen ein und drückt dann die richtige Tastenkombination, um ein Dateiende anzuzeigen, so enthält das Array drei Elemente. Hierbei enthält jedes Element einen String, der auf ein Newline-Zeichen endet. Dies entspricht den eingegebenen Zeilen, die ihrerseits auf ein Newline-Zeichen enden (Return-Taste).

Praktischerweise können Sie chomp eine Liste von Strings übergeben, und es entfernt die Newline-Zeichen aus allen Listenelementen auf einmal. Zum Beispiel:

 @zeilen = <STDIN>;  # alle Zeilen einlesen
 chomp(@zeilen);     # alle Newline-Zeichen entfernen

Üblicher ist es jedoch, diese Anweisung so schreiben, wie wir es schon vorher kennengelernt haben:

 chomp(@zeilen = <STDIN>); # Zeilen ohne die Newline-Zeichen einlesen

Auch wenn Sie diesen Code in den eigenen vier Wänden gern so schreiben dürfen, wie Sie wollen, werden die meisten Perl-Programmierer die zweite, kompaktere Schreibweise erwarten.

Es ist offensichtlich (wenn auch nicht für jeden), daß diese Eingabezeilen nur einmal gelesen werden können.27 Ist einmal das Dateiende erreicht, gibt es auch keine weitere Eingabe mehr zu lesen.

Und was passiert nun, wenn die Eingabe aus einer 400 MB großen Log-Datei kommt? Der Zeileneingabe-Operator wird alle Zeilen einlesen und dabei jede Menge Arbeitsspeicher verbrauchen.28 Wieder einmal versucht Perl hier nicht, Ihnen irgendwelche Grenzen aufzuzwingen. Statt dessen werden sich die übrigen Benutzer Ihres Systems (mal ganz abgesehen vom Administrator) zu Recht bei Ihnen beschweren. Wenn die Menge an Eingabedaten zu groß wird, sollten Sie in der Regel eher eine Methode verwenden, die nicht alle Daten auf einmal in den Speicher einliest.

Übungen

Die Lösungen zu den folgenden Übungen finden Sie in Anhang A:

  1. [6] Schreiben Sie ein Programm, das eine mehrzeilige Liste von Strings bis zum Dateiende-Zeichen einliest und diese in umgekehrter Reihenfolge wieder ausgibt. Kommt die Eingabe von der Tastatur, müssen Sie diese durch die Eingabe von Control-D (Unix) bzw. Control-Z (Windows) abschließen.
    Zur Lösung
  2. [12] Schreiben Sie ein Programm, das eine Liste von Zahlen (jeweils auf einer separaten Zeile) bis zum Dateiende (-zeichen) einliest und dann für jede Zahl den dazugehörigen Namen aus der untenstehenden Liste ausgibt. (Diese Liste muß in Ihrem Programm hartcodiert werden, sie muß also im Quellcode Ihres Programms vorkommen.) Wenn dies zum Beispiel die Zahlen 1, 2, 4 und 2 wären, sollten die ausgegebenen Namen Fred, Betty, Dino und Betty sein. .
    Zur Lösung
 Fred Betty Barney Dino Wilma Pebbles Bambam
  1. [8] Schreiben Sie ein Programm, das eine Liste von Strings (jeweils auf einer separaten Zeile) einliest. Danach sollen die Strings nach ASCII-Werten geordnet ausgegeben werden. Wenn Sie also die Strings Fred, Barney, Wilma, Betty eingeben, sollte die Ausgabe folgendermaßen aussehen: Barney Betty Fred Wilma. Befinden sich alle Strings auf einer Zeile oder auf verschiedenen? Können Sie die Strings auch auf die jeweils andere Weise ausgeben? .
    Zur Lösung

Fußnoten

1

In Perl beginnen die Indizes im Gegensatz zu anderen Sprachen immer mit null. In früheren Perl-Versionen war es möglich, den Startwert für die Indizierung von Listen und Arrays zu ändern (nicht nur für eine bzw. eines, sondern für alle auf einmal!). Larry wurde später klar, daß dies eher ein schlechtes Feature sei. Daher wird von einem Ge-(oder Miß-)brauch dieser Möglichkeit dringend abgeraten. Wenn Sie jedoch furchtbar neugierig sind, so sehen Sie sich in der perlvar-Manpage die Dokumentation zur Variablen $[ an.

2

Die Syntax ist niemals zweideutig - knifflig vielleicht, aber niemals zweideutig.

3

Die wichtigste Ausnahme besteht darin, daß die kontrollierende Variable in einer foreach-Schleife ein einfacher Skalar sein muß, wie wir später in diesem Kapitel sehen werden. Weitere Ausnahmen sind etwa der »indirect object slot« und der »indirect filehandle slot« bei print und printf.

4

Machen Sie hierfür die häßliche Syntax der C-Shell verantwortlich. Glücklicherweise müssen wir uns so etwas nicht allzuoft ansehen.

5

Diese Methode wird manchmal angewandt, um die Größe eines Arrays »vorzudefinieren«, damit Perl nicht jedesmal, wenn ein Array wächst, neuen Speicher zuweisen muß. Sollten Sie dies tatsächlich einmal brauchen, finden Sie in der Perl-Dokumentation weitere Informationen.

6

Anders als in Sprachen wie C, die keine einfache Möglichkeit bieten, dies zu tun. C-Programmierer benutzen hierfür in der Regel irgendein Makro oder verwenden eine Variable, um den Wert zwischenzuspeichern.

7

Das stimmt soweit für skalare Variablen. Arrayvariablen erhalten statt dessen eine leere Liste, wie wir gleich sehen werden.

8

Wir schummeln hier ein wenig, da wir davon ausgehen, daß das Array steine vor dieser Anweisung noch keinen Inhalt hatte. Hätte etwa $steine[7] bereits einen Wert, so hätte diese Zuweisung keinen Einfluß auf das Element.

9

Larry sagt, er habe das Dollar- und das at-Zeichen gewählt, da sich diese Zeichen auch als $kalar (skalare Variable) und @rray (Arrayvariable) lesen lassen. Wenn Sie das jetzt nicht nachvollziehen können oder sich später nicht mehr daran erinnern - nicht so schlimm.

10

Wenn Sie etwas tiefer in Perl vorgedrungen sind, werden Sie auf eine Art von Skalar stoßen, die man Referenz nennt. Hiermit lassen sich Dinge erzeugen, wie zum Beispiel »Listen von Listen«. Aber auch hier wird nicht wirklich eine Liste in einer anderen gespeichert, sondern nur eine Referenz darauf.

11

Natürlich machen wir nur Spaß. Allerdings steckt in dieser Aussage ein Fünkchen Wahrheit. Allerdings bedeutet das Zugreifen auf Arrays mit Hilfe von Indizes, daß Sie die wirklichen Stärken von Perl verkennen. Wenn Sie pop, push und andere Operatoren verwenden, die die Indizierung vermeiden, läuft Ihr Code in der Regel wesentlich schneller als bei der Verwendung von Indizes. Außerdem lassen sich dadurch die »Einer zuviel oder zuwenig«-Fehler (oft auch »Zaunpfahl«-Fehler genannt) vermeiden. Gelegentlich kommt es vor, daß ein angehender Perl-Programmierer sich einen für C optimierten Sortieralgorithmus (mit einer Menge Index-Operationen) vornimmt (um zu sehen, welche Sprache schneller ist), diesen eins zu eins in Perl nachprogrammiert (wieder mit einer Menge Index-Operationen) und sich anschließend wundert, warum er so langsam ist. Die Antwort lautet: Mit einer Stradivari Nägel in die Wand zu schlagen gilt in der Regel nicht als gutes Handwerk.

12

Unsere Leser mit höherer Bildung erkennen hierin ein Tautologie.

13

Um genau zu sein: Das Trennzeichen ist der Wert der speziellen Variablen $", die standardmäßig ein Leerzeichen ist.

14

Da Sie gerade fragen: Vor der Version 5 wäre ein unbenutzter Arrayname einfach nicht interpoliert worden. "fred@feuerstein.edu" könnte also ein String sein, der eine E-Mail-Adresse enthält. Diese Herangehensweise (»Perl tut schon, was ich meine«) geht nur so lange gut, wie niemand eine Variable mit dem Namen @feuerstein einfügt - plötzlich könnte es nämlich sein, daß der String sich in "fred.edu" oder etwas Schlimmeres verwandelt.

15

Wenn Sie die Warnungen eingeschaltet haben, ist es sehr gut möglich, daß Perl Sie daran erinnert, daß die Zahl "2*4" etwas komisch aussieht.

16

Es sei denn, der Variablenname wäre im gegenwärtigen Geltungsbereich als lexikalische Variable deklariert worden, wodurch Sie anstelle einer im gegenwärtigen Package lokalen Variablen eine lexikalisch lokale Variable bekommen - mehr dazu in Kapitel 4.

17

Es sei denn natürlich, Perl erwartet etwas vollkommen anderes. Diese anderen Kontext-Arten werden hier nicht behandelt. Niemand weiß tatsächlich genau, wie viele Arten von Kontext Perl benutzt. Die größten Hirne der Perl-Gemeinde haben sich bis jetzt noch nicht auf eine Antwort geeinigt.

18

Dies ist genauso, wie Sie es aus natürlichen Sprachen kennen. Wenn ich einen grammatischen Fehler mache, werden Sie es auch sofort bemerken, da Sie bestimmte Wörter auch an der richtigen Stelle erwarten. Nach einiger Zeit werden Sie Perl ebenfalls auf diese Art lesen, vorerst müssen Sie jedoch noch über die Bedeutung nachdenken.

19

Die Liste kann hierbei eine beliebige Anzahl von Elementen enthalten, also auch nur ein einziges oder auch gar keins. Wichtig ist nur, daß es sich um eine Liste und nicht um einen Skalar handelt.

20

Um genau zu sein, ist der tatsächliche Name des Arrays @leute einfach nur leute. Das @-Zeichen ist nur ein Qualifier (Qualifizierungszeichen, das anzeigt, um welche Art von Variable es sich handelt).

21

Im Bezug auf diesen Abschnitt gibt es jedoch keinen Unterschied zwischen einem Ausdruck, der eine Liste zurückgibt und einem, der einen skalaren Wert zurückgibt. Jeder Ausdruck kann sowohl eine Liste, als auch einen skalaren Wert zurückgeben, je nachdem, in welchem Kontext er benutzt wird. Wenn wir hier also von listenerzeugenden Ausdrücken sprechen, meinen wir Ausdrücke, die typischerweise im Listenkontext benutzt werden. Diese können für Überraschungen sorgen, wenn sie unerwartet im skalaren Kontext benutzt werden (wie etwa reverse oder @fred).

22

Das ist nur fair. Larry hat, als er Perl entwickelt hat, schließlich auch versucht, wie Sie zu denken, um vorherzusagen, was Sie wollen!

23

Bei den meisten Algorithmen, die tatsächlich benutzt werden, besteht jedoch kein Bedarf, die Variable explizit zu leeren, sofern sie für den korrekten Geltungsbereich deklariert wurde. Diese Art von Zuweisung ist in Perl also eher selten. Was ein Geltungsbereich ist, zeigen wir im folgenden Kapitel.

24

Dies ist nur die Standardsystemeinstellung und kann mit dem stty-Kommando geändert werden. Sie können sich aber meistens darauf verlassen - wir haben noch kein Unix-System gesehen, das eine andere Zeichenfolge für das Dateiende verwendet hätte.

25

Genauer gesagt ist es das Betriebssystem, das »sieht«, daß die Control-Taste gedrückt wurde, und daraufhin dem Programm ein Dateiende meldet.

26

Manche Portierungen von Perl für DOS/Windows-Systeme enthalten einen Fehler. Hierdurch kann es passieren, daß die erste Zeile, die nach der Eingabe des Dateiende-Zeichens ausgegeben wird, nicht korrekt angezeigt wird. Sie können dieses Problem umgehen, indem Sie nach dem Lesen der Eingabe einfach eine leere Zeile ("\n") ausgeben.

27

Na gut: Kommt die Eingabe aus einer Quelle, auf die Sie die Funktion seek anwenden können, ist es möglich, an den Anfang zurückzugehen und noch einmal zu lesen. Aber das ist nicht, wovon wir hier reden.

28

Das ist typischerweise sogar mehr Speicher, als die Datei selbst eigentlich benötigt. Eine 400 MB große Datei kann also durchaus ein Gigabyte an Speicher verbrauchen. Perl tendiert dazu, Speicher zu verschwenden, um dadurch Zeit zu sparen. Das ist eigentlich ein guter Tausch; wenn Sie zuwenig Arbeitsspeicher haben, können Sie welchen dazukaufen; wenn Sie zuwenig Zeit haben - Pech gehabt.


TOC PREV Übungen NEXT INDEX

Copyright © 2002 by O'Reilly Verlag GmbH & Co.KG