6.3.5
Wichtige Sprachelemente
Wir werden uns nun systematisch wichtigen Perl-Sprachelementen zuwenden. Behalten Sie immer die Erkenntnisse aus vorhergehendem Abschnitt im Hinterkopf - besonders der Semikolon ist wichtig, wenn Sie eigene Programme schreiben.
Wir haben diesen Abschnitt mit einigen Beispielen garniert. Wenn Sie die Beispiele ausprobieren wollen, müssen Sie die Prozedur aus dem ersten Abschnitt wiederholen - Texteditor öffnen, Beispiel dort einfügen, Datei speichern und schließlich den Perl-Interpreter starten. Wenn Sie unter Windows arbeiten, empfehlen wir Ihnen das sleep 3600; am Ende des Codes. Die Beispiele sind nicht für einen (direkten) Einsatz im Web gedacht. Soll heißen: um die Beispiele im Internet ansehen zu können, müssen Sie sie entsprechend anpassen. Dabei halten Sie sich am besten an das Hallo-Welt-Programm, aus dem Sie die letzten beiden Zeilen entfernen und durch den Beispiel-Code ersetzen. Wenn Sie die Beispiele unter Linux ausprobieren wollen, müssen Sie natürlich noch die erste Zeile des HalloWelt-Programms hinzufügen.
Wenn Sie innerhalb der Beispiele Zeilen sehen, die mit einem Größer-Zeichen (>) beginnen, gehört diese Zeile nicht zum Code selbst. So ausgezeichnete Zeilen enthalten das, was bei einem Ausführen des zugehörigen Beispiels ausgegeben würde.
Wir sind nun startklar für das eigentlich Tutorial und beginnen mit einer recht einfachen Lektion: den Kommentaren.
6.3.5.1 Der Kommentar
Kommentare werden vom Perl-Interpreter ignoriert. Sie sind also nur für den Menschen gedacht, der den Quellcode später einmal lesen soll. Überschätzen Sie sich nicht: Sie werden, wenn Sie nach einem halben Jahr versuchen, Ihren alten Code zu bearbeiten, einige sinnvolle Kommentare zu schätzen wissen.
Kommentare setzt man durch das Raute-Zeichen (#). Alles, was hinter diesem Zeichen bis zum Ende der Zeile folgt, wird ignoriert.
Ein Beispiel:
# Jetzt kommt der HTML-Header:
print "Content-type: text/html\n\n";
Übrigens ist die erste Zeile des "Hallo Welt"-Programms eine Ausnahme: sie wird nicht ignoriert, obwohl sie mit einer Raute beginnt. Solche Ausnahmen sind selten. Bleiben Sie also fürs Erste bei der Faustregel, dass Rauten immer Kommentare einleiten.
Der Kommentar ist ein nützliches Mittel, wenn es darum geht, ein Script zu debuggen. Folgendes Script ist fehlerhaft (und die Ausgabe kommt von Perl und sagt Ihnen, dass da etwas nicht stimmt):
print "abc;
> Can't find string terminator '"' ...
Wo ist der Fehler? Sie können einfach die Zeile, in der Sie den Fehler vermuten, auskommentieren, um herauszufinden, ob Sie mit Ihrer Vermutung richtig lagen:
# Liegt der Fehler hier?
# print "abc;
> ...
6.3.5.2 Blöcke
Blöcke in Perl sind eine simple Sache: sie beginnen mit einer geschweiften Klammer und enden mit einer geschweiften Klammer:
{
# Ich bin im Block
print "abc";
}
Sie können Blöcke setzen, wo immer Sie wollen. Denken Sie nur daran, dass zu einer öffnenden Klammer auch immer eine schließende gehört.
Auch Verschachtelungen sind möglich:
{
# Ich in Block 1
{
# Und ich bin ich Block 2
}
}
Mit Blöcken lassen sich einige nützliche Dinge anstellen. Lassen Sie sich bitte vorerst damit vertrösten, dass Blöcke enorm wichtig sind für Perl - ohne sie kein größeres Programm.
6.3.5.3 Variablen
Variablen sind wie Container. Sie stecken etwas hinein, und dort bleibt es, bis Sie es herausholen. Praktischerweise sind diese Container ziemlich flexibel: im Prinzip können Sie herein stecken, was immer Sie wollen. Sie müssen noch nicht einmal wissen, was genau im Container ist, um mit ihm arbeiten zu können.
Gerade letzter Aspekt macht die Programmierung erst flexibel: Variablen ermöglichen es, abstrakt zu programmieren.
6.3.5.3.1 Variablen setzen
Variablen beginnen in Perl immer mit dem Dollar-Zeichen ($, wird übrigens gerne vergessen und sorgt dann für Fehler). Mit dem Gleichheitszeichen wird Variablen ein Wert zugewiesen:
$variable = "wert";
Selbstverständlich ist es auch möglich, einer Variable den Wert einer anderen zuzuweisen:
$variable1 = $variable2;
Bitte beachten Sie: Der Wert von $variable2 wird dupliziert. Wenn Sie also später irgend etwas mit $variable1 anstellen wollen, wirkt sich das nicht auf $variable2 aus.
6.3.5.3.2 Notationen
Achten Sie darauf, immer die richtigen Notationen für Strings (Zeichenketten, also im Grunde alles, was keine Zahl ist) und Zahlen zu verwenden. Strings stehen in Anführungszeichen, Zahlen werden so geschrieben, wie man es aus dem Alltag kennt. Nur das bei uns übliche Komma muss durch den Punkt ersetzt werden, wenn mit gebrochenen Zahlen gearbeitet werden soll:
$var = "zeichenkette";
$var = 12;
$var = 12.2;
Vollkommen falsch wäre:
$var = zeichenkette;
Achten Sie auch darauf, nicht aus Versehen einen Variablennamen in Anführungszeichen zu setzen.
6.3.5.3.3 Quoting und Interpolation
Interpolation
Sehen Sie sich folgenden Code an:
$variable1 = "Ich denke, ";
$variable2 = "$variable1 also bin ich";
print $variable2;
> Ich denke, also bin ich

Wenn Sie innerhalb doppelter Anführungszeichen einen Variablennamen verwenden, wird der durch den Wert der Variable ersetzt. Wenn Sie dieses Verhalten nicht wünschen, verwenden Sie einfach Anführungszeichen:
$variable1 = "Ich denke, ";
$variable2 = '$variable1 also bin ich';
print $variable2;
> $variable1 also bin ich

Andere Quoting-Mechanismen
Das Setzen eines Strings in Anführungszeichen nennt man "Quoting", weil hier Perl klar gemacht wird, dass es sich um eine Zeichenkette handelt, und nicht etwa um den Namen einer Variablen oder einen Befehl. Sie kennen jetzt schon zwei Quoting-Zeichen: doppelte und einfache Anführungszeichen. Wäre doch gelacht, wenn es nicht noch mehr gäbe:
$var = qq(Ich denke, also bin ich);
$var2 = qq($var <= berühmtes Zitat);
$var3 = q($var <= berühmtes Zitat);
# \n in der nächsten Zeile - was ist das?
# Siehe dazu den nächsten Abschnitt
print $var2, "\n";
print $var3, "\n";
> Ich denke, also bin ich <= berühmtes Zitat
> $var <= berühmtes Zitat

qq() erfüllt also die gleiche Funktion wir doppelte Anführungszeichen, q() dagegen arbeitet wie einfache Anführungszeichen.
Wofür braucht man so viele Quoting-Mechanismen? Sehen Sie sich folgendes Beispiel an:
# Da stimmt doch was nicht...
print "Paul sagt:"Ich bin Paul"";
> Bareword found where operator expected...
Das Problem ist hier, dass innerhalb der Zeichenkette das Zeichen verwendet werden soll, das die Zeichenkette eigentlich umschließt. Deshalb verwendet man hier einen anderen Quoting-Mechanismus...
print qq(Paul sagt:"Ich bin Paul");
> Paul sagt:"Ich bin Paul"Paul sagt:"Ich bin Paul"
Sonderzeichen
In einem vorherigen Beispiel wurde das verwendet:
print $var2, "\n";
Wir wissen von print, dass es alles ausgibt, was hinter ihm steht. Und wir sahen bei der Ausführung des Beispiels, dass hier in zwei Zeilen ausgegeben wurde. Genau dafür war das rätselhafte \n verantwortlich: Es heißt "Zeilenumbruch hier". Selbstverständlich lässt es sich auch direkt verwenden:
print "Viele\n\nviele\n\nZeilen";
> Viele
>
> viele
>
> Zeilen
Das funktioniert nur in doppelten Anführungszeichen oder qq(). In einfachen Anführungszeichen würde es einfach ignoriert.
Andere solche Zeichen sind \t (Tabulator) oder \\ (Backslash). Der Backslash innerhalb einer Zeichenkette gibt dem nächsten Zeichen oft eine andere Bedeutung. Daher müssen, wenn ein Backslash ausgegeben werden soll, zwei Backslashes verwendet werden:
# \n soll ausgegeben werden, kein
# Zeilenumbruch
print "\n"; # Falsch!
print "\\n"; # Richtig!
Dieser Mechanismus wird auch dann wichtig, wenn Sonderzeichen ausgegeben werden sollen, beispielsweise das @:
# @ mit Backslash:
print "webmaster\@aboutwebdesign.de";
> webmaster@aboutwebdesign.de
6.3.5.3.4 Namensräume
Wenn Sie eine Variable setzen, können Sie ihre Gültigkeit begrenzen. Soll heißen: Sie definieren eine Variable, die nur von bestimmten Stellen (ihrem Block) aus zugänglich ist.
Welche Gründe könnte es geben, das zu tun? Im Allgemeinen wird es als guter Stil angesehen, Variablen lokal zu deklarieren, ihre Gültigkeit also damit zu begrenzen. Diese Vorgehensweise verhindert Konflikte: manchmal verwendet man den Namen einer Variablen aus Versehen doppelt. Wenn die Variable dann global (also unbegrenzt gültig) ist, hat man ein Problem. Zudem verhindert man so unnötigen Speicherbereich, denn sobald der Gültigkeitsbereich einer Variablen verlassen wurde, wird die Variable gelöscht.
Wenn Sie sich dafür entscheiden, Variablen lokal zu machen (es gibt nur sehr wenige Fälle, in denen das nicht angebracht ist), verwenden Sie das Schlüsselwort my, wenn Sie auf die Variable das erste Mal zugreifen. Die Variable ist dann nur innerhalb des Blocks gültig, in dem sie erzeugt wurde.
Spätere Zugriffe auf die Variable laufen genauso ab wie Zugriffe auf globale Variablen:
# Globale Variable
$var1 = "abc";
# Zugriffe:
print $var1;
$var1 = "fjfjf";
# Lokale Variable
my $var2 = "abc";
# Zugriffe genauso:
print $var2;
$var2 = "fjfjf";
Um das Konzept des Blocks in Zusammenhang mit lokalen Variablen noch einmal zu verdeutlichen, haben wir hier noch ein Beispiel:
{
# Globale Variable
$var1 = "testwert";
}
print $var1;
> testwert
{
# Lokale Variable, nur in
# diesem Block gültig
my $var2 = "testwert";
}
# Hier ist der Block verlassen,
# $var2 hat also keinen Wert
# mehr.
print $var2;
> (keine Ausgabe)

6.3.5.4 Operatoren
Operatoren sind die Sprachelemente, die andere Elemente miteinander verknüpfen. Die meisten Operatoren nehmen die beiden Dinge, die rechts und links neben ihnen stehen, und verknüpfen sie auf irgendeine Art miteinander. 5 + 4 ist ein gutes Beispiel, hier werden 5 und 4 zum Wert 9 verknüpft. Das nennt man übrigens Ausdruck: Erst werden alle Operatoren angewandt, dann ergibt das ein Ergebnis.
In Perl funktioniert das genau so, wie man es normalerweise erwarten würde:
6.3.5.4.1 String-Operatoren
Es gibt einen Operator, um zwei Strings miteinander zu verknüpfen: den Punkt-Operator.
$a = "String1 ";
$b = "String2";
print $a.$b;
> String1 String2

Dabei ist Perl im Umgang mit Strings und Zahlen äußerst flexibel. Sie können mit dem Punkt-Operator auch einen String mit einer Zahl oder eine Zahl mit einer Zahl verknüpfen. In solchen Fällen nimmt Perl einfach an, dass die Zahl ein String ist, denn Strings können schließlich auch Zahlen enthalten.
print "Zahl: ".10;
> Zahl: 10
# Klammerung notwendig, um
# klar zu machen, dass keine
# Kommazahl gemeint ist
print ((10).(10));
> 1010

6.3.5.4.2 Numerische Operatoren
Perl unterstützt alle bekannten numerischen Operatoren. Sie funktionieren alle nach diesem Muster:
$a = 5 + 4;
print $a,"\n";
> 9
$a = 10;
$b = 3;
$c = $a + $b;
print $c,"\n";
> 13
print 3*4,"\n";
> 12

Es gibt die Operatoren + (Addition), - (Subtraktion), * (Multiplikation), / (Division) und ** (Potenzierung).
6.3.5.4.3 Abkürzungen
Perl-Programmierersollen faul sein. Damit müssen sie es einfach hassen, zu viel tippen zu müssen. Daher wurden einige Abkürzungen geschaffen, um so etwas wie $var1 = $var1 + 5; abzukürzen (erhöht $var1 um 5). Man kann stattdessen einfach $var1 += 5; schreiben.
Das klappt noch mit einigen anderen Operatoren:
$v += 5;
$v *= 5;
$v /= 5;
$v .= "Anhaengsel";
Zusätzlich dazu wurde noch eine spezielle Möglichkeit geschaffen, das Erhöhen einer Variable um 1 eleganter zu formulieren:
$c++ erhöht die Variable $c um 1. $c-- tut genau das Gegenteil.
6.3.5.4.4 Logische Operatoren
Logische Operatoren arbeiten etwas anders: Sie arbeiten nur mit den Werten "wahr" und "falsch", symbolisiert durch 1 und 0.
Dabei gelten nur 0-Werte, leere und nicht definierte Werte als falsch, alle anderen sind wahr.
Logische Operatoren werten zunächst die Werte aus, auf die sie angewendet werden, d.h. sie überprüfen, ob diese Werte wahr oder falsch sind. Dann verknüpfen sie die beiden Werte.
Der Operator and gibt 1 zurück, wenn beide Werte, auf die er angewendet wird, wahr sind. Der Operator or verlangt, dass mindestens einer dieser Werte wahr sein muss, wenn eine 1 zurückgegeben werden soll.
Der Operator not dagegen wird nur auf einen Wert angewendet: Er kehrt ihn einfach um.
Folgende Beispiele werden das vielleicht etwas verdeutlichen:
# Wahr, da 1 immer wahr
print (1 and 1);
> 1
# and verlangt, dass beide wahr sein müssen,
# gibt jetzt also Falsch zurück
print (0 and 1);
> 0
print (1 or 1);
> 1
# or dagegen reicht es, wenn einer
# der Werte wahr ist
print (1 or 0);
> 1
# not kehrt um
print (not 1);
> 0
print (not 0);
> 1
# Das klappt auch wunderbar mit Zeichenketten,
# die prinzipiell wahr sind, solange sie nicht
# leer sind
print ('a' and 1);
> 1
6.3.5.4.5 Vergleichsoperatoren
Vergleichsoperatoren ähneln den logischen Operatoren: sie geben als Ergebnis immer Wahr oder Falsch zurück.
Jedoch ist ihre Funktion etwas komplexer als die der logischen Operatoren: sie vergleichen die beiden Werte, wie der Name eben schon sagt.
Hier sollte zwischen Zeichenketten- und Zahlenkettenvergleichen unterschieden werden. Die wichtigsten Operatoren sind wohl die, die auf Gleichheit prüfen: eq und ==, ersterer für Strings, letzterer für Zahlen:
print (1 == 1);
> 1
print (1 == 12);
> 0
print ("gut" eq "schlecht");
> 0
print ("eins" eq "eins");
> 1
Logischerweise gibt es auch Umkehr-Operatoren für einen Test für Nicht-Gleichheit: für Zeichenketten ist das ne, für Zahlen dagegen !=.
Auf die anderen Operatoren für Strings gehen wir hier nicht weiter ein - sie werden so gut wie nie benötigt. Anders dagegen sieht es mit den anderen Operatoren für Zahlenvergleiche aus, deren Bedeutung für die Praxis ungleich größer ist: > (größer), < (kleiner), <= (kleiner oder gleich) und >= (größer oder gleich). Angewendet werden sie genauso wie die anderen Vergleichsoperatoren.
6.3.5.4.6 Operatoren-Rangfolge
Bestimmt erinnern Sie sich noch an die alte mathematische Grundregel: Punktrechnung geht vor Strichrechnung. Diese Regel existiert auch in Perl:
print 8*5+3;
> 43

Aber beginnen wir etwas weiter vorne: Es ist möglich, beliebige Operatoren miteinander zu verknüpfen. Daher gibt es Regeln, die genau festlegen, welcher Operator jeweils Priorität hat. Daher mussten wir auch im letzten Abschnitt klammern: and hat eine so niedrige Priorität, dass anderenfalls der erste Werte von print ausgewertet würde.
Klammern jedoch haben grundsätzlich die höchste Priorität: es lohnt sich daher, viel und häufig zu klammern, um sich selbst vor Flüchtigkeitsfehlern zu schützen, gerade dann, wenn man Operatoren verwendet, deren Priorität nicht automatisch aus dem Mathematik-Unterricht bekannt ist.
6.3.5.5 Arrays
6.3.5.5.1 Definition
Wir hatten einmal gesagt, Variablen seien Container, die man mit beliebigem Inhalt füllen könne. Einen Beweis sind wir bisher schuldig geblieben: schließlich haben wir lediglich Zahlen und Zeichenketten in Variablen gespeichert. Wir werden nun zwei neuen Formen zuwenden, Daten zu speichern: Arrays und Hashes.
Arrays sind Listen. Eine ganz einfache Sache also. Verwendet werden sie so:
# Array erzeugen
@array = ('eins', 'zwei', 'drei');
# Ein Element der Liste ausgeben
print $array[0], "\n";
> eins
print $array[2], "\n";
> drei
# Ein Element zu setzen, ist genauso einfach
$array[2] = "neuer Wert!";
print $array[2], "\n";
> neuer Wert

Sie sehen, wir haben am Anfang etwas geschwindelt: Es gibt auch Variablen, die mit etwas anderem als dem Dollarzeichen beginnen. So z.B. das Array, das das @-Zeichen am Anfang trägt. Aber das nur dann, wenn auf das Array als Ganzes zugegriffen wird. Sonst wird weiterhin das altbekannte Dollarzeichen verwendet und die Variable wird "Skalar" genannt. Ein Array ist also logischerweise aus einer Reihe von Skalaren aufgebaut. Jedes einzelne Element des Arrays ist eine Variable wie jede andere und kann wiederum mit beliebigem Inhalt gefüllt werden.
Dabei ist Perl wie immer ziemlich flexibel. Sie können auch auf Elemente des Arrays zugreifen, die bisher noch gar nicht erzeugt wurden. Auch eine gegenseitige Zuweisung von Arrays ist möglich, genau wie bei Skalaren:
# Array als leere Liste erzeugen
# Ist sinnvoll, um sich selbst
# vor Fehlern zu schützen
@array = ();
$array[10] = "Das elfte Element";
print $arrray[10], "\n";
> "Das elfte Element";
# Array kopieren
@array2 = @array;

Fassen wir also noch einmal zusammen: Arrays sind Listen. Spricht man das gesamte Array an, verwendet man ein @-Zeichen vor dem Namen des Arrays. Will man einem ganzen Array Inhalt zuweisen, setzt man die Werte in runde Klammern und trennt sie mit Kommata. Will man dagegen auf ein einzelnes Element zugreifen, verwendet man das Dollarzeichen am Anfang und spezifiziert das Element, auf das zugegriffen werden soll, mit einem Zahlenwert, der in eckigen Klammern direkt hinter dem Array-Namen steht. Die Zählung dieser Werte beginnt bei 0, d.h. der Wert mit dem Index 0 ist der erste Wert und der Index 10 steht für den elften Wert.
6.3.5.5.2 Die Länge von Arrays
Manchmal müssen Sie herausfinden, welchen Wert der größte Index des Arrays hat. Verwenden Sie in einem solchen Fall die Schreibweise $#array. $#array+1 gibt also an, wie viele Elemente im Array vorhanden sind:
# my funktioniert auch mit Arrays
my @array = ('eins','zwei', 'drei');
print "Das Array hat so viele Elemente:", $#array+1;

Sehr hilfreich ist das, wenn Sie nicht wissen, wie groß ein Array eigentlich ist, z.B. weil es mit CGI-Daten gefüllt wurde:
# my funktioniert auch mit Arrays
my @array = ('eins','zwei', 'drei', 'hundert');
# Letztes Element ausgeben:
print $array[$#array];

6.3.5.5.3 Array-Funktionen
Es gibt einige nützliche Funktionen, die beim Umgang mit Arrays sehr hilfreich sind. Sie werden jetzt zum ersten Mal mit anderen Funktionen als print konfrontiert: Gehen Sie davon aus, dass diese neuen Funktionen sehr ähnlich arbeiten. Viele Funktionen liefern einen Rückgabewert, der dann in einer Variable gespeichert werden kann. Fast alle Funktionen erwarten auch, so wie print, Argumente. Die sollten dann in runden Klammern stehen, um Probleme zu vermeiden. Die folgenden Beispiele werden das etwas klarer machen.
pop
pop tut zwei Dinge gleichzeitig: Es entfernt das letzte Element eines Arrays und liefert es zurück.
# Jetzt hat @array drei Elemente
my @array = ('eins','zwei', 'drei');
# Nach der nächsten Zeile sind es nur
# noch zwei Elemente
my $letzter_wert = pop(@array);
print $letzter_wert;
> drei

push
push fügt eine Liste am Ende eines Arrays an. Dabei kann diese hinzuzufügende Liste natürlich auch aus nur einem Element bestehen:
my @array = ('eins','zwei', 'drei');
push(@array, 'vier');
# Letztes Element ausgeben:
print $array[3], "\n";
> vier
# Und jetzt: ein Array an ein anderes
# anhängen
my @array2= ('fuenf', 'sechs');
push(@array, @array2);
# Letztes Element ausgeben:
print $array[3], "\n";
> sechs

shift und unshift
shift und unshift arbeiten genauso wie pop und push. Sie entfernen das erste Element (shift) und fügen etwas an den Anfang des Arrays an (unshift).
my @array = ('eins','zwei', 'drei');
my $erstes_element = shift(@array);
# Erstes Element ist entfernt,
# jetzt ist zwei vorne
print $array[0];
> zwei
unshift(@array, $erstes_element);
# Und jetzt ist eins wieder vorne:
print $array[0];
> eins

join
join fügt alle Elemente eines Elements zu einem String zusammen. Zwischen die einzelnen Elemente kommt ein Trennzeichen:
my @gaeste = ('Klaus', 'Hans', 'Alex');
print "Eingeladen: ", join(', ', @gaeste);

Das Trennzeichen ist also das erste Argument, das Array, aus dem eine Zeichenkette gemacht werden soll, ist das zweite Argument. Das Array wird dabei nicht verändert.
sort
sort sortiert ein Array und gibt das Ergebnis zurück. Das ursprüngliche Array wird dabei nicht verändert:
my @a = ('x', 'z', 'y');
my @sorted = sort(@a);
print join(',', @sorted);

Dabei kann explizit zwischen numerischer und alphabetischer Sortierung gewählt werden:
my @a = (1, 2, 3, 10);
my @numerisch = sort {$a <=> $b} (@a);
my @alphabetisch = sort {$a cmp $b} (@a);
print "Numerisch: ", join(',', @numerisch), "\n";
print "Alphabetisch: ", join(',', @alphabetisch), "\n";
> Numerisch: 1,2,3,10
> Alphabetisch: 1,10,2,3

Wie Sie sehen, führt also eine alphabetische Sortierung, die übrigens Standard ist, wenn man sort ohne Zusatz verwendet, zu seltsamen Ergebnissen, wenn Zahlen sortiert werden sollen.
reverse
reverse kehrt die Reihenfolge der Elemente in einem Array um und gibt das Ergebnis zurück. Das Ausgangs-Array bleibt unberührt.
my @a = (1, 2, 3, 10);
my @umgekehrt = reverse(@a);
print "Ursprünglich: ", join(',', @a), "\n";
print "Umgekehrt: ", join(',', @umgekehrt), "\n";
> Ursprünglich: 1,2,3,10
> Umgekehrt: 10,3,2,1
6.3.5.6 Hashes
6.3.5.6.1 Definition
Hashes werden auch assoziative Arrays genannt. Soll heißen: auch Hashes sind Listen, auf die jedoch mit einer Zeichenkette, nicht mit einer Zahl zugegriffen wird. Diese Zeichenkette wird Schlüssel genannt. Die Werte innerhalb eines Hashes haben keine feste Reihenfolge.
Sehen Sie sich folgendes Beispiel an:
my %hash;
$hash{a} = 'Test-Wert';
print $hash{a};
> Test-Wert

So weit also recht einfach: statt des @-Zeichens haben wir hier ein Prozent-Zeichen. Anstelle eckiger Klammern verwenden wir geschweifte.
Praktisch sind Hashes, weil ihre Handhabung in vielen Fällen umkomplizierter ist als die Verwendung eines Arrays:
my %kunde;
$kunde{name} = "Meier";
$kunde{strasse} = "Mainweg";
$kunde{ort} = "Muenchhausen";
$kunde{telefon} = "44593";

6.3.5.6.2 Hash-Funktionen
Genauso wie für Arrays gibt es auch für Hashes bestimmte Funktionen, die den Umgang mit ihnen erleichtern.
keys
Wer irgendwie auf alle Werte eines Hashes zugreifen will, muss die Schlüssel kennen. keys gibt eine Liste aller Schlüssel eines Hashes zurück.
my %kunde;
$kunde{name} = "Meier";
$kunde{strasse} = "Mainweg";
$kunde{ort} = "Muenchhausen";
$kunde{telefon} = "44593";
my @schluessel = keys(%kunde);
print join(', ', @schluessel);
# Die Reihenfolge der Schlüssel
# ist bei Ihnen eventuell
# anders!
> telefon, ort, strasse, name

Ist Ihnen aufgefallen, dass wir es hier wieder mit einem Array zu tun haben? Man wird die Dinger aber auch einfach nicht los.. ;-)
Um jetzt alle Werte wirklich sinnvoll verarbeiten zu können, brauchen Sie noch ein bisschen mehr Hintergrundwissen. Damit müssen Sie sich leider bis zum Abschnitt über Schleifen gedulden. Dort finden Sie dann aber auch ein sinnvolles Beispiel.
delete
Um ein Schlüssel-Wert-Paar aus einem Hash zu löschen, verwenden Sie die delete-Funktion:
my %kunde;
$kunde{name} = "Meier";
$kunde{strasse} = "Mainweg";
$kunde{ort} = "Muenchhausen";
$kunde{telefon} = "44593";
delete $kunde{telefon};
my @schluessel = keys(%kunde);
print join(', ', @schluessel);
# Die Reihenfolge der Schlüssel
# ist bei Ihnen eventuell
# anders!
> ort, strasse, name

6.3.5.7 Andere Funktionen
Es gibt noch viele andere Funktionen, die dem Programmierer das Leben erleichtern. Die müssen Sie kennen, bevor Sie ernsthafte Anwendungen schreiben können.
6.3.5.7.1 chop/chomp
chop entfernt das letzte Zeichen einer Zeichenkette:
my $zeichenkette = "test";
chop($zeichenkette);
print $zeichenkette;
> tes

Die Zeichenkette wird dabei also grundsätzlich verändert. chomp überprüft vorher, ob das letzte Zeichen ein \n (Zeilenumbruch) ist. Nur dann wird es entfernt.
6.3.5.7.2 index
index sucht eine Zeichenkette innerhalb einer anderen und gibt ihre Position zurück:
my $zeichenkette = "abcdefg";
print index($zeichenkette, 'c');
> 2

Sie sehen, dass hier das erste Zeichen die Position 0 hat. Wird die Teilzeichenkette nicht gefunden, wird -1 zurückgegeben. Es ist zusätzlich möglich, als drittes Argument noch eine Startposition für die Suche anzugeben.
6.3.5.7.3 substr
substr extrahiert einen Teil einer Zeichenkette:
my $zeichenkette = "abcdefg";
print substr($zeichenkette, 3, 3);
> def

Der erste Parameter ist also der String, aus dem extrahier wird. Der zweite Parameter gibt die Startposition an, und der dritte, wie viele Zeichen extrahiert werden sollen.
Es ist optional möglich, noch einen vierten Parameter anzugeben. Wenn das getan wird, wird die extrahierte Teilzeichenkette durch den vierten Parameter ersetzt. Im Zusammenspiel mit index lässt sich so ein kleines Programm bauen, das das erste Vorkommen einer Zeichenkette durch eine andere ersetzt. Hier der Code:
my $basis_zeichenkette = "Klaus sucht das Haus!";
my $suchen = "Klaus";
my $ersetzen = "Peter";
my $position = index($basis_zeichenkette, $suchen);
substr($basis_zeichenkette, $position, length($suchen), $ersetzen);
print $basis_zeichenkette;
> Peter sucht das Haus

Unberücksichtigt bleibt leider, dass die Möglichkeit, dass der Such-String gar nicht im Ausgangs-String vorhanden ist, ignoriert wird. Zusätzlich benutzen wir die Funktion length, die Sie bisher noch nicht kennen. Sie ermittelt - Überraschung! - die Länge einer Zeichenkette.
6.3.5.7.4 length
length ermittelt die Länge einer Zeichenkette:
my $zeichenkette = "abcdefg";
print length($zeichenkette);
> 7

6.3.5.7.5 die
Die Funktion die beendet das Programm. Ein Beobachter von außen könnte zu dem Schluss kommen, dass der Tod gewaltsam war ;-). Soll heißen: die wird eingesetzt, um unerwartete Fehler abzufangen.
die("Fehler bei XYZ...");
Das erste Argument ist optional und wir ausgegeben.
6.3.5.7.6 exit
exit wird verwendet, um das Programm natürlich zu beenden. Parameter sind keine zwingend erforderlich.
6.3.5.7.7 eval
eval ist eine enorm praktische, gleichzeitig aber auch etwas komplizierte Funktion. Sie wird entweder verwendet, um Fehler abzufangen, oder um Perl-Code auszuführen, der zum Zeitpunkt der Programmierung eventuell noch gar nicht bekannt ist.
Das Abfangen von Fehlern wird in diesem Beispiel gezeigt:
eval {
# Division durch Null ist nicht
# erlaubt!
print 10/0;
};
print $@;
> Illegal division by zero...
Die Spezialvariable $@ wird nur dann gesetzt, wenn beim letzten eval ein Fehler aufgetreten ist. Lag dagegen kein Fehler vor, wird die Variable explizit geleert. Es ist möglich, das mit Bedingungsanweisungen zu verknüpfen, aber dazu später mehr.
Vermeiden Sie, solange Sie noch am Anfang Ihrer Perl-Karriere stehen, die Verwendung von eval zum Ausführen von Code. Wir zeigen Ihnen trotzdem, wie es geht:
my $code = qq(print "ABC";);
eval($code);
> ABC

Der Unterschied zum vorherigen Beispiel: es wird eine Zeichenkette, kein Block an eval übergeben.
Achten Sie darauf, in solchen Fällen grundsätzlich die Variable $@ zu überprüfen. Im Abschnitt "Bedingungen" gibt es ein Beispiel dazu.
6.3.5.7.8 Zeit-Funktionen
time gibt die Anzahl der Sekunden seit dem 1.1.1970 zurück (zumindest ist das auf den meisten Systemen so. Der Macintosh aber zählt z.B. die Sekunden seit einem Datum im Jahre 1904).
localtime verarbeitet diese Zahl und macht eine lokale Zeitangabe daraus: Es werden Sekunden, Minuten, Stunden, Tag, Monat, Jahr, Tag des Monats und Tag des Jahres zurückgegeben. Ein weiterer Rückgabewert ist wahr, wenn zu dem übergebenen Zeitpunkt die Sommerzeit gilt.
Um beispielsweise das aktuelle Datum auszugeben, schreiben Sie:
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$sommerz) = localtime(time);
$year = $year + 1900;
$mon = $mon + 1;
print "Es ist der $mday.$mon.$year";

Übrigens ist das ein gutes Beispiel, um zu sehen, wie Listen zurückgegeben werden.
Ansonsten ist der Code simpel. Sie müssen nur darauf achten, dass die Angaben ihre kleinen Tücken haben: zum Jahr muss 1900 dazuaddiert werden, zum Monat 1.
6.3.5.7.9 Funktionen selbst definieren
Wäre doch gelacht, wenn man so praktische Funktionen nicht auch selbst definieren könnte. Natürlich geht es, und es ist ziemlich einfach.
Der folgende Code zeigt die wichtigen Elemente einer Funktionsdefinition:
print &summe(3,2);
sub summe
{
my $argument = shift;
my $argument2 = shift;
return ($argumentd + $argument2);
}

Funktionsdefinitionen werden eingeleitet vom Schlüsselwort sub. Danach folgt der Funktionsname und ein Block. Der Block enthält den Code, der zur Funktion gehört. Innerhalb der Funktion stehen die Argumente im Array @_ zur Verfügung. Tricky: wenn shift kein Argument bekommt, arbeitet es automatisch mit dem @_-Array.
Wenn man eine Rückgabe erzeugen will, verwendet man das Schlüsselwort return. Argument ist entweder ein Rückgabewert oder auch eine Liste.
Aufgerufen wird die Funktion wie alle vorherigen Funktionen auch. Klammern sind Pflicht, vor den Funktionsnamen sollte ein Und-Zeichen (&) gestellt werden.
Übrigens lässt sich unser Suchen-und-Ersetzen-Beispiel von eben auch als Funktion definieren:
sub ersetzen
{
my $basis_zeichenkette = $_[0];
my $suchen = $_[1];
my $ersetzen = $_[2];
my $position = index($basis_zeichenkette, $suchen);
substr($basis_zeichenkette, $position, length($suchen), $ersetzen);
return $basis_zeichenkette;
}
print &ersetzen("Ich will ein Haus", "Haus", "Computer");

Wir haben hier eine etwas andere Form gewählt, auf die Parameter zuzugreifen. Wir sagten ja, dass die Parameter im Array @_ zur Verfügung stehen. Genauso, wie man auf Elemente des Array @gaeste mit $gaeste[0] zugreifen kann, funktioniert hier der Zugriff über $_[0] etc.
Es ist übrigens unwesentlich, von wo die Funktion aufgerufen wird. Eben stand der Aufruf über der Funktion, jetzt unter ihr. Es ist genauso möglich, dass der Aufruf am Anfang der Datei steht und die Funktion selbst ganz unten.
Funktionen sind eine sehr praktische Sache. Sie schaffen damit Ordnung in Ihrem Code. Verwenden Sie sie, wann immer es angemessen scheint!
6.3.5.8 Bedingungen
6.3.5.8.1 if
Um irgendwann einmal auf ein Ereignis reagieren zu können, muss man unterscheiden: wurde Taste A oder Taste B gedrückt? Hat die Datei mehr oder weniger als 10.000 Zeilen?
Für die Bearbeitung solcher Fragen gibt es die verzweigten Bedingungen. Mit ihnen lässt sich das ausdrücken, was im Deutschen mit den Wörtern "Wenn ..., dann ...", "Wenn nicht das, anstatt dessen aber etwas anderes zutrifft, dann ..." und "sonst" ausdrücken lässt. Im Klartext: praktisch beliebig komplexe Ausdrücke sind formulierbar. Sehen Sie sich folgendes Code-Beispiel in Pseudo-Sprache an:
Wenn die Zahl A größer als 5 ist, führe aus:
{
Wenn die Zahl B gleich 10 ist, führe aus:
{
irgendeine Anweisung;
}
Und für alle andere Fälle führe das aus:
{
irgendeine Anweisung;
}
}
Wenn die Zahl A dagegen gleich 5 ist, führe aus:
{
irgendeine Anweisung;
}
Und für alle andere Fälle führe das aus:
{
irgendeine Anweisung;
}
Recht einfach verständlich, nicht wahr? Übrigens zeigt dieses Beispiel eine Verschachtelung: es ist möglich, innerhalb eines Blocks weitere Verschachtelungen durchzuführen.
In Perl sieht das nicht viel anders aus. Sie verwenden einfach die Operatoren, die Sie schon kennen. Folgendes Beispiel hat die gleiche Funktion wie vorheriger Pseudo-Code, funktioniert aber nicht direkt in Perl, da der Interpreter Probleme mit irgendeine Anweisung; bekommen würde.
my $a = 5;
my $b = 12;
if ($a > 5)
{
if ($b = 10)
{
irgendeine Anweisung;
}
else
{
irgendeine Anweisung;
}
}
elsif ($a == 5)
{
irgendeine Anweisung;
}
else
{
irgendeine Anweisung;
}
Wie deutlich wird, sind Bedingungen grundsätzlich in Klammern zu schreiben. Dabei handelt es sich übrigens um Ausdrücke. Wenn Sie sich das und die Funktionsweise von Operatoren noch einmal ins Gedächtnis rufen wollen, sollten Sie den entsprechenden Abschnitt noch einmal lesen.
Im Beispiel ist zu sehen, dass else für "sonst" steht. Auch der Rest ist recht einfach zu verstehen: if leitet eine bedingte Verzweigung ein. Wenn man zusätzliche, parallele Bedingungen verwenden will, schreibt man danach elsif. Dieser Teil kann nur dann ausgeführt werden, wenn die vorherige if-Bedingung nicht zutraf. Es ist auch möglich, mehrere elsif-Blöcke hintereinander zu verwenden.
Bedingungen sind für viele Anwendungen zwingend erforderlich. So z.B. auch für das Sicherstellen eines korrekten Ablaufs, indem man beispielsweise das Ergebnis einer eval-Funktion testet. Das geht so:
eval {
# Division durch Null ist nicht
# erlaubt!
print 10/0;
};
if ($@)
{
die("Oh oh.. hier liegt ein Fehler vor!");
}
Wir erinnern uns: $@ ist nur dann nicht leer, wenn ein Fehler vorlag. Nur dann ist $@ also wahr, und dann wird die die-Anweisung ausgeführt.
6.3.5.8.2 Andere Möglichkeiten
Es gibt noch eine andere, schnellere Form einer Bedingung, die allerdings nicht immer anwendbar ist. Oft werden Sie so etwas wie das hier sehen:
open(DATEI, "<test") || die ("Datei konnte nicht geöffnet werden");
Das || ist eine stärker bindende Form des or, hat also eine höhere Priorität. Beide Operatoren zeigen ansonsten das gleiche Verhalten. or funktioniert folgendermaßen: Erst wird das ausgewertet, was links steht, dann das, was rechts steht. Wenn das, was links steht, aber schon wahr ist, wird der rechte Teil gar nicht mehr ausgewertet.
Das obige Beispiel funktioniert so: die open-Funktion (die im Übrigen gleich besprochen wird) gibt Wahr zurück, wenn sie ordnungsgemäß funktioniert hat. Gab es jedoch einen Fehler, wird Falsch zurückgegeben. Nur dann wird auch der rechte Teil ausgewertet, die die-Anweisung. Um die auszuwerten, muss sie jedoch erst einmal ausgeführt werden, womit das Programm dann beendet ist.
6.3.5.9 Schleifen
Stellen Sie sich vor, Sie müssten ein- und denselben Code mehrmals ausführen. Ihn mehrmals einzutippen, wäre weder elegant noch flexibel, ist also keine gute Lösung. Wie gut, dass es Schleifen gibt: Die nämlich führen einen Block mehrmals hintereinander aus. Wann Schluss ist, können Sie genau festlegen.
6.3.5.9.1 Die for-Schleife
for-Schleifen werden auch "Zählschleifen" genannt, weil bei ihnen eine Variable immer weiter hochgezählt wird. Hat die Variable einen bestimmten Wert erreicht, so wird die Schleife beendet:
for (my $i = 0; $i < 10; $i++)
{
print $i;
}
> 0123456789

Innerhalb der Klammern der for-Schleife wird erst die Variable auf einen Startwert gesetzt, dann wird eine Bedingung formuliert, die gelten muss, solange die Schleife ausgeführt wird, und zum Schluss kommt noch das, was mit der Variable nach einem Schleifendurchlauf gemacht wird: hier wird sie jedes Mal um 1 erhöht. Die Teile werden mit einem Semikolon getrennt.
6.3.5.9.2 Die while-Schleife
Steigen wir direkt ein:
while($a == 10)
{
...
}
Die while-Schleife wird also ausgeführt, solange der Ausdruck in Klammern wahr ist.
foreach
Die foreach-Schleife dient dazu, eine Liste der Reihe nach abzuarbeiten:
my @liste = ('a', 'b');
foreach my $element (@liste)
{
print $element
}
> ab

Dabei kann die Variable natürlich frei gewählt werden. Übrigens wird der Zugriff auf alle Elemente eines Hashes praktisch immer mit foreach realisiert:
my %kunde;
$kunde{name} = "Meier";
$kunde{strasse} = "Mainweg";
$kunde{ort} = "Muenchhausen";
$kunde{telefon} = "44593";
foreach my $key (keys %kunde)
{
my $wert = $kunde{$key};
print "$key = $wert";
}
> telefon = 44593 ort = Muenchhausen strasse = Mainweg name = Meier

Trickreich, nicht wahr? Erst wird eine Liste aller Hash-Schlüssel erzeugt, dann wird diese Liste abgearbeitet und jedes Mal der zugehörige Wert ausgegeben.
6.3.5.10 Dateizugriff
Perl wurde entwickelt, um Dateien schnell verarbeiten zu können. Wir zeigen Ihnen, wie man Dateien zeilenweise einliest:
6.3.5.10.1 Datei lesen
my $dateiname = "/data/xyz.dat";
open(DATEI, '<'.$dateiname) or die "Kann $dateiname nicht öffnen";
while(<DATEI>)
{
my $zeile = chomp($_);
# Jetzt irgendwas mit der Zeile machen
}
close(DATEI);
open öffnet eine Datei. Das erste Argument ist dabei ein Name für das Dateihandle (kann ziemlich frei gewählt werden, pro Datei möglichst ein Handle), das zweite der Pfad zur Datei. Soll die Datei geöffnet werden, muss dem Pfad ein < vorangestellt werden. Eine or-Abfrage, ob die Datei erfolgreich geöffnet werden konnte, ist unverzichtbar!
Danach wird die Datei mit while ausgelesen: Bei jedem Aufruf gibt <DATEIHANDLE> die nächste Zeile von DATEIHANDLE zurück. Erst, wenn DATEIHANDLE am Ende ist, wird Falsch zurückgegeben.
Innerhalb der while-Schleife kann dann über die Variable $_ auf die aktuelle Zeile zugegriffen werden.
Am Ende eines Dateizugriffs steht immer das Schließen des Handles mit close.
6.3.5.10.2 Datei schreiben
Das Schreiben einer Datei verläuft sehr ähnlich:
# Was in die Datei rein soll?
my $towrite = "xyz";
my $dateiname = "/data/xyz.dat";
open(DATEI, '>'.$dateiname) or die "Kann $dateiname nicht öffnen";
print DATEI $towrite;
close(DATEI);
Der Unterschied zum Lesen: wir verwenden print für den Schreibvorgang und verwenden ein > anstelle eines <. Wer diesen Code ausführt, löscht den alten Inhalt der Datei. Wer das nicht möchte, ersetzt das > durch ein >>, dann werden die mit print geschriebenen Daten ans Ende der Datei gehängt.
6.3.5.10.3 Datei sperren
Stellen Sie sich vor, zwei Leute schreiben gleichzeitig eine Datei. Das kann nur zu Unordnung führen. Daher gibt es einen Mechanismus, Dateien zu sperren.
use Fcntl;
open(DATEI, '>'.$dateiname) or die "Kann $dateiname nicht öffnen";
flock(DATEI, LOCK_EX) or die "Kann $dateiname nicht sperren";
Danach geht es wie gewohnt weiter. Das macht aber nur dann Sinn, wenn nicht nur Schreib-, sondern auch Lesezugriffe gesperrt werden:
use Fcntl;
open(DATEI, '<'.$dateiname) or die "Kann $dateiname nicht öffnen";
flock(DATEI, LOCK_SH) or die "Kann $dateiname nicht sperren";
|
6.3.6
Fortgeschrittene Programmierkonzepte
Sie werden im Folgenden etwas über fortgeschrittene Programmierkonzepte erfahren. Soll heißen: Wenn Sie sich die Zeit nehmen, die hier vorgestellten Konzepte zu verstehen, werden Sie wirklich davon profitieren. Wir beginnen mit einer Möglichkeit, Perl-Code über verschiedene Dateien zu verteilen. Dabei beschreiben wir sowohl, wie man externe Perl-Module verwendet, als auch, wie selbst Code ausgelagert werden kann. Danach reißen wir das Thema der objektorientierten Programmierung kurz an. OOP ist oft unverzichtbar, wenn fremde Quellcodes oder von Anderen programmierte Klassen verwendet werden sollen. Wir beschränken uns dabei darauf, zu besprechen, wie OOP verwendet wird. Wie selbst OOP programmiert wird, würde den Rahmen dieses Kapitels sprengen.
6.3.6.1 Quellcode auslagern
Oft ist es hilfreich, Perl-Code über mehrere Dateien zu verteilen. Das schafft Übersicht. Es gibt in Perl zudem eine einfache Möglichkeit, auf den Code von anderen Programmierern, in Modulen gespeichert, zuzugreifen. So muss man das Rad nicht ständig neu erfinden. Die beiden Themen gehören zusammen, weil beide darauf angewiesen sind, auf irgendeine Art und Weise externe Dateien einzubinden.
6.3.6.1.1 Perl-Module
Perl-Module sind eine tolle Sache: Sie geben Zugriff auf ein unermessliches Archiv von vorprogrammierten Funktionen, CPAN genannt. Im CPAN finden sich Module für fast jede denkbare Anwendung, so z.B. für alle häufiger angewendeten Netz-Protokolle. Ein FTP-Server ist mit dem passenden CPAN-Modul beispielsweise gar kein Problem.
Wir wollen Ihnen nun zeigen, wie Module installiert und verwendet werden.
Module installieren
Zunächst einmal gilt es, sich das gewünschte Modul aus dem Netz zu besorgen. Das macht allerdings nur Sinn, wenn Sie auch administrativen Zugriff auf den Rechner verfügen, auf dem das Modul installiert werden soll. Wollen Sie dagegen ein Modul auf einem Internet-Server verwenden, so ist das nicht ohne Weiteres möglich: Das müssen Sie dann mit dem verantwortlichen Mitarbeiter des Providers abklären.
Wenn Sie ein Modul aber lokal installieren wollen, ist das nicht weiter schwierig: Unter Windows verwenden Sie einfach den ppm. Wie man ihn genau bedient, wird in der ActiveState-Perl-Anleitung erklärt. Hier nur die Kurzform: Sie klicken auf "Ausführen" im Start-Menü und geben in das Eingabefeld ppm ein. Sie bestätigen und eine Text-Konsole öffnet sich. Dort geben Sie install Modul-Name ein.
Wenn Sie ein anderes Betriebssystem verwenden, ist die Prozedur etwas komplexer: Zunächst einmal laden Sie sich das gewünschte Modul vom CPAN herunter. Module sind dort fast immer im .tar.gz-Format gespeichert.Enthalten ist eine Readme-Datei, die genau beschreibt, wie das Modul installiert werden kann. Normalerweise müssen Sie lediglich vier oder fünf Befehle ausführen, dann ist das Modul installiert. Kleiner Haken: Oft wird ein C-Compiler benötigt, der allerdings auf Unix-Systemen sowieso fast immer vorhanden ist.
Module verwenden
Verwenden Sie einfach den use-Befehl, um ein Modul einzubinden:
use CGI;
Um diesen Befehl verwenden zu können, müssen Sie den Namen des Moduls kennen, den Sie der Dokumentation entnehmen können. Es ist zusätzlich möglich, anzugeben, dass nur bestimmte Teile eines Moduls geladen werden sollen:
use CGI::Carp qw(fatalsToBrowser);
Module importieren die Funktionen, die sie zur Verfügung stellen, in den Namensraum, aus dem sie aufgerufen werden. Soll heißen: Wenn Sie ein Modul aufgerufen haben, können Sie seine Funktionen einfach direkt verwenden.
Die Funktionen eines Moduls
Nur woher erfahren Sie, welche Funktionen ein Modul bietet und wie diese verwendet werden? Die Antwort ist einfach und für Sie wahrscheinlich nicht befriedigend: Sie müssen die Dokumentation des Moduls durchgehen. Dort werden Sie meist auch Beispiele zur Verwendung finden. In diesem Tutorial besprechen wir lediglich die Verwendung von zwei Modulen, CGI und DBI.
6.3.6.1.2 Selbst Code auslagern
Wenn Sie nicht gerade selbst ein Modul programmieren wollen (das ist nicht ganz einfach) und Ihren eigenen Code trotzdem auf verschiedene Dateien aufteilen wollen, gibt es natürlich eine Möglichkeit.
Namensräume
Vorher jedoch müssen Sie noch etwas über Namensräume wissen. Beginnen wir mit einer simplen Aussage: Globale Variablen sind gar nicht global. Sie sind lediglich innerhalb ihres Packages einfach anzusprechen. Wenn Sie nicht explizit ein Package angeben, geht Perl davon aus, dass Sie das Standard-Package main verwenden wollen. Wenn Sie dagegen ein anderes Package verwenden wollen, müssen Sie den Namen des Packages im Variablen-Bezeichner angeben:
$variable = "abc";
# Das gleiche:
$main::variable = "abc";
Der Package-Name steht also am Anfang des Variablen-Bezeichners, gefolgt von einem doppelten Doppelpunkt.
Sie können selbstverständlich explizit angeben, wie das aktuelle Package heißen soll. Verwenden Sie dafür den Befehl package. Auch Package-übergreifende Zugriffe sind möglich, wie das nächste Beispiel zeigt.
Bitte beachten Sie: Variablen, die mit my erzeugt wurden, fallen nicht unter diesen Mechanismus. Sie sind innerhalb ihres Blocks verfügbar, nicht innerhalb ihres Packages.
Kommen wir nun zum eben angekündigten Beispiel:
package Variablen;
$eins = "a";
$zwei = "b";
package main;
print $Variablen::eins, $Variablen::zwei;
> ab

Code verteilen
Und wo ist der Zusammenhang zu unserem eigentlichen Thema? Wir schlagen vor, jeder einzelnen Datei ihren eigenen Package-Namen zu geben. Die Dateien sollten dabei ins gleiche Verzeichnis gelegt werden, damit der folgende Beispiel-Code funktioniert.
Inhalt der Datei test.pl:
require "datei1.pl";
print $p1::variable;
print &p1::funktion;
Inhalt der Datei datei1.pl:
package p1;
$variable = "test-variable ";
sub funktion
{
return "test-rückgabe";
}
Die Ausgabe:
> test-variable test-rückgabe
Sie sehen also: require bindet eine andere Datei ein. Um ärgerliche Probleme zu vermeiden, sollten Sie auf jeden Fall so vorgehen, wie in unserem Beispiel gezeigt, nämlich pro Datei ein Package zu definieren.
Wenn Sie trotzdem Fehlermeldungen angezeigt bekommen (das passiert dann, wenn das Arbeitsverzeichnis nicht gleich dem Verzeichnis ist, in dem das Script liegt), dann müssen Sie an den Anfang des Scripts ein chdir '/pfad/des/scripts'; stellen.
6.3.6.2 OOP in Perl
Um das gleich vorneweg zu stellen: wir gehen hier nicht darauf ein, wie selbst Klassen in Perl erstellt werden können. Wir beschränken uns darauf, zu zeigen, wie Objekte verwendet werden. Dieses Wissen benötigen Sie, weil beispielsweise viele Module ihre Schnittstelle ojektorientiert zur Verfügung stellen.
Wir wollen auch hier nicht weiter auf die Konzepte der OOP (Objektorientierten Programmierung) eingehen. Im JavaScript-Know-How-Kapitel gibt es dazu etwas detailliertere Informationen. Da dieses Tutorial jedoch auch ohne Lesen der JavaScript-Abschnitte verständlich sein soll, hier das wichtigste in Kürze: Klassen sind Baupläne für Objekte. Objekte können Funktionen und Variablen enthalten, OOP-spezifisch Methoden und Eigenschaften genannt. Von einer Klasse können beliebig viele Objekte konstruiert werden, dieser Vorgang wird Instanzierung genannt. Objekte werden in Variablen gespeichert.
6.3.6.2.1 new
Ein Objekt wird konstruiert, indem man das Schlüsselwort new verwendet:
my $cgi = new CGI;
Bitte lassen Sie sich von solchen Konstrukten nicht verwirren:
use CGI;
my $cgi = new CGI;
Die use-Anweisung hat nichts mit OOP zu tun. Sie bindet lediglich das CGI-Modul ein.
Die danach folgende Zeile dagegen hat eine Menge mit OOP zu tun: der Name der Variablen ist frei wählbar, dass hier Modulname, Klassenname und Variablenname übereinstimmen, ist keineswegs zwingend. Der Klassenname (das CGI hinter dem new) ist dagegen nicht frei wählbar, sondern durch die im CGI-Modul definierte Klasse vorgegeben. Oder, anders: alles, bis auf den Variablennnamen $cgi, ist nicht frei wählbar.
6.3.6.2.2 Zugriff auf Methoden und Eigenschaften
Sie greifen auf Methoden und Eigenschaften eines Objekts mit Hilfe des ->-Operators zu. Dabei ist es egal, ob es sich um eine Eigenschaft oder Methode handelt, der Operator wird immer in der gleichen Art und Weise verwendet:
use CGI;
my $query = new CGI;
# Jetzt: Zugriff auf Eigenschaft
# Übrigens: diese Eigenschaft existiert
# nicht wirklich, dient also nur
# als Beispiel
$query->eigenschaft = "abc";
# Oder auch: Eigenschaft auslesen
my $wert = $query->eigenschaft;
# Jetzt kommt die Methode (existiert
# übrigens wirklich)
# Auch Methoden können wie Funktionen Werte
# zurückgeben und mit Argumenten gefüttert
# werden.
my $parameter = $query->param('xyzz');
6.3.6.3 Fazit
Wenn Sie mit OOP und Modulen Probleme haben, wären Sie nicht der Erste. Es gibt kaum einen Perl-Beginner, der diese Konzepte im ersten Anlauf versteht. Die folgenden Abschnitte setzen beide Techniken ein: Sehen Sie sich die einfach einmal an, das wird helfen, wenn Sie noch Verständnisschwierigkeiten haben.
|