9.3 Perl
Bis jetzt wurden in diesem Kapitel zwei kompilierte Programmiersprachen behandelt, eine prozedurale und eine objektorientierte. In diesem Abschnitt wird eine völlig anders konzipierte Variante erläutert: Perl ist eine interpretierte Skriptsprache, die verschiedene nützliche Eigenschaften von C, den Unix-Shell-Skriptsprachen sowie den Textprozessorsprachen sed und awk in sich vereint.
Perl wurde 1987 von Larry Wall entwickelt, als er im Rahmen eines Programmierauftrags umfangreiche Datenbestände koordinieren musste, die auf Rechnern an beiden Küsten der USA verteilt waren. Heute wird Perl vorwiegend von Unix-Systemadministratoren verwendet, um ihre tägliche Arbeit zu erleichtern. Außerdem ist Perl die bevorzugte Sprache für CGI-Skripte, die klassische Form der Webanwendung. Die Perl-Mottos »There’s more than one way to do it« und »Make easy things easy and hard things possible« geben einen Eindruck von der Vielseitigkeit, Praxisnähe und Leistungsfähigkeit dieses Werkzeugs.
Die Abkürzung Perl steht eigentlich für »Practical Extraction and Report Language«, wird aber von Larry Wall und den anderen Perl-Hackern manchmal auch als »Pathologically Eclectic Rubbish Lister« (etwa: »krankhaft sammelwütiger Auflister für jeden Mist«) bezeichnet. Solcher Humor ist ein typisches Merkmal der Perl-Gemeinde und hat auch die Sprache selbst beeinflusst (und umgekehrt!).
Obwohl Perl unter Unix entwickelt wurde und eng mit den besonderen Eigenschaften dieses Betriebssystems verknüpft ist, ist der Perl-Interpreter für viele verschiedene Betriebssysteme verfügbar. Wenn Sie eine Unix-Variante verwenden, ist Perl höchstwahrscheinlich bereits auf Ihrem Rechner installiert. Falls Sie mit Windows arbeiten, bietet sich die hierfür optimierte Perl-Distribution ActivePerl an, die Sie unter http://www.activestate.com herunterladen können.
Die aktuelle Version von Perl ist 5.18. Die parallel seit einigen Jahren in Entwicklung befindliche Version 6 bringt viele Neuerungen, insbesondere eine virtuelle Maschine namens Parrot, auf die neben Perl auch andere Sprachen aufsetzen können.
Um ein Perl-Programm auf Ihrem Rechner auszuführen, müssen Sie es dem Perl-Interpreter übergeben. Unter Unix geschieht dies durch die Shebang-Zeile zu Beginn des Skripts, die dem System das Verzeichnis mitteilt, in dem sich der Interpreter befindet:
Eine auf diese Weise präparierte Datei müssen Sie nur noch mithilfe von chmod +x ausführbar setzen, um sie zu starten. Unter Windows wird dagegen auf der Kommandozeile der Perl-Interpreter explizit aufgerufen:
C:\>perl meinprogramm.pl
Dennoch wird auch unter Windows die Shebang geschrieben; für Einsatzgebiete wie die CGI-Programmierung ist sie dort auch wichtig. Natürlich sieht sie ein wenig anders aus als unter Unix, zum Beispiel so:
#!C:/perl/bin/perl.exe
Beachten Sie, dass auch unter Windows, anders als üblich, der / (Slash) als Pfadtrennzeichen verwendet wird.
Empfehlenswert ist übrigens die folgende Variante der Shebang:
#!/usr/bin/perl -w
Die Option -w schaltet ausführliche Warnmeldungen ein, die Sie auf mögliche Ungenauigkeiten oder Zweideutigkeiten hinweisen können. Dies kann auf Dauer Ihren Programmierstil erheblich verbessern.
9.3.1 Das erste Beispiel
Damit Sie Perl genauer mit den anderen in diesem Kapitel vorgestellten Programmiersprachen vergleichen können, sehen Sie hier die Perl-Fassung des erweiterten »Hallo Welt«-Programms:
#!/usr/bin/perl -w
print "Hallo Welt!\n";
print "Ihr Name, bitte: ";
$name = <>;
chomp $name;
print "Hallo $name!";
Speichern Sie das Skript unter dem Namen hallo.pl, und führen Sie es aus wie eingangs beschrieben.
Wie Sie sehen, ist dieses Perl-Skript die bisher kürzeste Variante des Programms. Das liegt vor allem daran, dass Perl-Skripte keine besonderen Formalitäten einhalten müssen: Es gibt kein explizites Hauptprogramm; ein Skript ist im einfachsten Fall lediglich eine Folge normaler Anweisungen. Im Folgenden werden die Zeilen des »Hallo Welt«-Skripts nacheinander beschrieben:
- print "Hallo Welt!\n";
print "Ihr Name, bitte: ";
Mithilfe von print werden Inhalte auf die Standardausgabe geschrieben. In Perl können Sie die Klammern um Funktionsargumente weglassen; dies ist nicht immer übersichtlich, aber speziell bei print allgemein üblich. - $name = <>;
Mithilfe des etwas merkwürdig aussehenden Operators <> wird eine Zeile Text von der Standardeingabe gelesen. Wie im Folgenden noch besprochen wird, kann zwischen den Klammern auch eine Datei angegeben werden, aus der gelesen werden soll.Im vorliegenden Fall wird die gelesene Zeile in der Variablen $name gespeichert. In Perl beginnen die Namen der verschiedenen Arten von Variablen mit speziellen Zeichen. Eine Variable, die einen einzelnen Wert speichern kann (Skalar genannt), fängt zum Beispiel mit einem Dollarzeichen an.
- chomp $name;
Die Funktion chomp entfernt den Zeilenumbruch vom Ende eines Strings. Der Zeilenumbruch, mit dem die eingegebene Zeile endet, wird nämlich von <> mit eingelesen und stört in vielen Fällen. - print "Hallo $name!";
Einer der wichtigsten Vorteile der Einleitung von Variablennamen durch spezielle Zeichen besteht darin, dass innerhalb von Strings eine Variablensubstitution durchgeführt wird: Da Variablen an ihren Anfangszeichen erkennbar sind, kann der Perl-Interpreter sie auflösen.
9.3.2 Elemente der Sprache Perl
Im Folgenden werden verschiedene wichtige Bestandteile von Perl systematisch vorgestellt.
Variablen
Variablen funktionieren in Perl ein wenig anders als in typisierten Compilersprachen wie C oder Java. Wie viele andere interpretierte Skriptsprachen ist Perl nämlich eine untypisierte Sprache. Variablen besitzen keinen festen Datentyp, sondern ihr gespeicherter Inhalt wird je nach Kontext interpretiert. Außerdem können sie nacheinander verschiedene Werte annehmen, sodass Zuweisungen wie die folgenden erlaubt sind:
$a = "hallo"; # String
$a = 3; # ganze Zahl
$a = 4.678; # Fließkommazahl
Eine Variable existiert automatisch durch die erste Wertzuweisung und muss nicht deklariert werden. Dadurch werden Programme einerseits kürzer und kompakter, aber andererseits werden Fehler nicht so leicht bemerkt, weil Perl sich nicht beschwert, wenn Sie sich bei einem Variablennamen verschreiben. Eine Variable, die in einem Ausdruck verwendet wird, ohne dass ihr ein Wert zugewiesen wurde, hat den speziellen Wert undefined. Dies führt möglicherweise zu unerwarteten Ergebnissen, nicht aber zu einer Fehlermeldung.
Für längere Programme bietet es sich deshalb an, die strenge Wertüberprüfung zu aktivieren. Diese Option verlangt, dass jede Variable bei ihrer ersten Verwendung explizit deklariert wird. Die Wertüberprüfung wird zu Beginn eines Programms (meist unmittelbar unter der Shebang) folgendermaßen eingeschaltet:
Innerhalb eines normalen Perl-Skripts werden Variablen bei strenger Wertüberprüfung durch ein vorangestelltes my deklariert; in den im Folgenden vorgestellten Subroutinen mit local:
#!/usr/bin/perl
use strict;
my $zahl1; # explizite Deklaration
my $zahl2 = 3; # implizite Deklaration bei Wertzuweisung
$zahl3 = 7; # Fehlermeldung: Nicht deklariert!
Perl kennt drei Arten von Variablen: Skalare, Arrays und Hashes.
- Ein Skalar ist eine normale »Einzelvariable«. Ihr Wert ist ein einzelner String, eine Zahl oder eine Referenz auf ein beliebiges Element. Die Namen von Skalaren beginnen mit einem Dollarzeichen, zum Beispiel $wert.
- Ein Array ähnelt der gleichnamigen Datenstruktur in C und Java, ist aber erheblich flexibler. Die Anzahl der Elemente im Array kann dynamisch erhöht oder vermindert werden. Der Name der gesamten Array-Variablen beginnt mit dem Zeichen @, beispielsweise @werte.
- Ein Hash, auch assoziatives Array genannt, ähnelt einem gewöhnlichen Array. Das Besondere daran ist allerdings, dass die Indizes für die einzelnen Felder keine aufeinanderfolgenden Integer-Werte sind, sondern beliebige Strings sein können. Der Name eines Hashs beginnt mit % wie etwa %wochentage.
Ein Array kann auf zwei Arten erzeugt werden: Entweder weisen Sie dem gesamten Array eine Liste als Wert zu, oder Sie erstellen sofort ein einzelnes Element des Arrays:
@sprachen = ("C", "Java", "Perl"); # Liste zuweisen
$betriebssysteme[0] = "Linux"; # Einzelnes Element
$betriebssysteme[1] = "MacOS X";
$betriebssysteme[2] = "MacOS 9";
$betriebssysteme[3] = "Windows";
Da die Elemente von Arrays Skalare sind, ist das Vorzeichen für ein einzelnes Element kein @, sondern ein $.
Bei der Formulierung ("C", "Java", "Perl") handelt es sich übrigens um eine Liste. Listen können nicht nur in Arrays gespeichert werden, sondern auch ein interessantes Eigenleben führen. Sie können sogar eine Liste skalarer Variablen als LVALUE verwenden! Dies ermöglicht beispielsweise die folgende praktische Schreibweise für den Tausch der Werte zweier Variablen:
($a, $b) = ($b, $a);
In fast jeder anderen Sprache benötigen Sie für einen solchen Tausch eine dritte Variable als Zwischenspeicher und müssen drei Anweisungen schreiben. In Java sieht die Tauschoperation für zwei int-Variablen zum Beispiel so aus:
int c = a; // Wert von a retten
a = b; // a wird überschrieben
b = c; // b erhält den alten Wert von a
Perl definiert darüber hinaus eine Reihe nützlicher Funktionen zur Behandlung von Arrays und Listen. Einige wichtige Beispiele sind folgende:
$w = pop(@array); # Den letzten Wert des Arrays ab-
# trennen und zurückgeben
push (@array, $w); # Skalar an ein Array anhängen
$w = shift (@array); # Den ersten Wert des Arrays ab-
# trennen und zurückgeben
unshift (@array, $w); # Skalar vor das erste Element
# eines Arrays setzen
Mithilfe der Funktionen pop, push, shift und unshift können Sie allerdings nicht nur einzelne Elemente von Arrays abtrennen oder ihnen hinzufügen, sondern auch Listen. Beispielsweise hängt die folgende Anweisung eine Liste mit zwei weiteren Programmiersprachen an das zuvor definierte Array @sprachen an:
push (@sprachen, ("C++", "C#"));
Interessant ist auch die Fähigkeit von Perl, eine automatische Schleife über alle Elemente eines Arrays zu bilden. Dazu wird die spezielle Kontrollstruktur foreach verwendet. Das folgende Beispiel gibt die Namen dreier in einem Array gespeicherter Prozessoren untereinander aus:
@prozessoren = ("Pentium 4", "Athlon", "PowerPC");
foreach $prozessor(@prozessoren) {
print "$prozessor\n";
}
Wenn Sie die Angabe der Schleifenzählervariablen (hier $prozessor) weglassen, stellt Perl übrigens automatisch die spezielle Variable $_ dafür zur Verfügung. Diese wird von vielen Funktionen automatisch verwendet, sofern kein anderes Argument angegeben wird. Die zuvor dargestellte foreach-Schleife ließe sich also auch so schreiben:
foreach (@prozessoren) {
print; # $_ ausgeben
print "\n"; # der fehlende Zeilenumbruch
}
Sie können ein Array auch zu einem Skalar zusammenfassen und umgekehrt. Die Anweisung split (/Muster/, String) zerlegt den angegebenen String an den Stellen, an denen das Muster (ein regulärer Ausdruck) vorkommt, und konvertiert ihn in ein Array. join (Ausdr, Array) fasst die Elemente des angegebenen Arrays zu einem String zusammen und setzt jeweils den angegebenen Ausdruck dazwischen:
$syslist = "Linux,MacOS X,MacOS 9,Windows";
@systeme = split (/,/, $syslist);
# ergibt Array mit Systemnamen
@sprachen = qw(C Java Perl);
$sprachlist = join (", ", @sprachen);
# ergibt "C, Java, Perl"
Ein Hash kann ebenfalls durch die Definition eines einzelnen Elements eingerichtet werden:
$wtage{'Mo'} = 'Montag';
Auch einzelne Elemente von Hashes sind skalar und beginnen deshalb mit einem $. Der Index eines Hash-Elements wird als Schlüssel (Key) bezeichnet. Alternativ können Sie den ganzen Hash auf einmal definieren:
%wtage = (Mo => 'Montag', Di => 'Dienstag',
Mi => 'Mittwoch', Do => 'Donnerstag',
Fr => 'Freitag', Sa => 'Samstag',
So => 'Sonntag');
Die spezielle Schreibweise Schlüssel => Wert erlaubt es, die Anführungszeichen um die Schlüsselnamen wegzulassen, solange diese keine problematischen Sonderzeichen enthalten – hier sind insbesondere Leerzeichen gemeint sowie Zeichen, die in Perl eine spezielle Bedeutung haben; mit Buchstaben, Ziffern und Unterstrichen machen Sie definitiv nichts falsch.
Auch über die Elemente eines Hashs lässt sich eine foreach-Schleife bilden. Dazu wird dem Namen des Hashs das spezielle Schlüsselwort keys vorangestellt. Die zuvor definierten Wochentage können Sie zum Beispiel so ausgeben:
foreach $key (keys %wtage) {
print "$key ist die Abkürzung für ${wtage{$key}}\n";
}
Wie Sie sehen, ermöglichen geschweifte Klammern hinter dem $-Zeichen die Auflösung komplexer Variablenkonstrukte innerhalb von Strings.
Ein weiteres interessantes Konstrukt im Zusammenhang mit Variablen ist die Referenz. Sie ist im Wesentlichen mit einem Zeiger in C oder einer Objektreferenz in Java vergleichbar: Referenzen verweisen auf beliebige Variablen, Subroutinen oder sonstige Elemente; eine Referenz wird durch einen Backslash (\)dargestellt. Beispiele:
$v_ref = \$var; # Referenz auf ein Skalar
$a_ref = \@array; # Referenz auf ein Array
$h_ref = \%hash; # Referenz auf ein Hash
Die umgekehrte Operation heißt Dereferenzierung. Sie wird in Perl durchgeführt, indem Sie dem Namen der Referenz das Zeichen für den Variablentyp voranstellen, auf den die Referenz verweist:
$$v_ref = 3; # indirekt auf $var zugreifen
@$a_ref.push ("hi"); # indirekt auf @array zugreifen
%$h_ref = (name => 'Klaus', alter => 42);
# indirekt auf %hash zugreifen
$$a_ref[0] = "hallo"; # indirekt auf ein Element
# von @array zugreifen
Referenzen sind unter anderem als Übergabewerte für Subroutinen nützlich (siehe im Folgenden). Eine weitere Möglichkeit, die sie bieten, ist die Konstruktion verschachtelter Arrays und Hashes, für die es keine andere Lösung gibt:
@schmitz = ("Klaus", "Erika", "Michael");
@mueller = ("Heinz", "Gisela", "Claudia");
@familien = (\@schmitz, \@mueller);
Um nun beispielsweise auf das erste Mitglied der zweiten Familie zuzugreifen, können Sie $familien[1][0] schreiben und erhalten "Heinz".
Ausdrücke und Operatoren
Viele der in Perl verfügbaren Literalen und Operatoren entsprechen denjenigen von C. Die besondere Flexibilität von Perl ergibt sich jedoch erst aus einer Reihe wichtiger Unterschiede. Einige von ihnen werden hier vorgestellt.
Für numerische Literale gelten dieselben Regeln wie in C. In Perl können Sie allerdings zusätzlich einen Unterstrich als Tausendertrennzeichen einsetzen, um große Zahlen übersichtlicher zu machen:
$milliarde = 1_000_000_000; # Wert: 1000000000
Die Raute (#) leitet übrigens den einzigen in Perl erlaubten Kommentar ein. Er reicht vom Auftreten dieses Zeichens bis zum Zeilenende.
Für die Formulierung von String-Literalen bestehen in Perl erheblich mehr Möglichkeiten als in C, ein separates Literal für ein einzelnes Zeichen existiert dagegen nicht. Im einfachsten Fall steht ein String-Literal in einfachen oder in doppelten Anführungszeichen. Während in doppelten Anführungszeichen die bereits angesprochene Variablensubstitution durchgeführt wird, bleiben Strings in einfachen Anführungszeichen stets wörtlich erhalten:
$geld = 100;
print "Ich habe $geld \$.\n"; # Wert: Ich habe 100 $.
print 'Ich habe $geld $\n'; # Wert: Ich habe $geld $\n
In einfachen Ausführungszeichen wird also nicht nur die Variablensubstitution, sondern auch die Ersetzung von Escape-Sequenzen wie \n unterdrückt. Lediglich \' für das einfache Anführungszeichen selbst und \\ für den Backslash werden aufgelöst.
In doppelten Anführungszeichen müssen Sie dagegen eine Reihe spezieller Zeichen als Escape-Sequenz schreiben, wenn Sie diese Zeichen als solche verwenden möchten. Neben den zu erwartenden Fällen \" und \\ betrifft dies auch \$ (das Dollarzeichen), \@ (für ein @) und \%.
Neben den beiden Arten von Anführungszeichen definiert Perl weitere Schreibweisen für String-Literale. Diese haben den Vorteil, dass Sie die Zeichen " oder ' – je nachdem – einfach als solche verwenden können:
- q/String/ ersetzt die einfachen Anführungszeichen, steht also für 'String'.
- qq/String/ wird statt doppelter Anführungszeichen gesetzt, ist also ein Ersatz für "String".
- qw/Ausdr1 Ausdr2 Ausdr3/ stellt keinen String dar, sondern ist eine kompakte Schreibweise für eine Liste einzelner Wörter. Die Langschreibweise dieser Liste wäre ('Ausdr1', 'Ausdr2', 'Ausdr3').
Das besonders Interessante an diesen speziellen Quoting-Verfahren ist, dass Sie statt des Slashs (/) auch verschiedene andere Zeichen verwenden können, um den Inhalt abzugrenzen. Sie können sich individuell für Zeichen entscheiden, die im jeweiligen String selbst nicht vorkommen. Gängige Beispiele sind q!String!, q(String) oder q{String}. Entweder werden also zwei gleiche Zeichen wie /.../, !...! oder |...| verwendet, oder aber zwei entgegengesetzte Klammern einer beliebigen Sorte.
Bei Operationen berücksichtigt Perl das Problem, dass die Inhalte von Variablen als unterschiedliche Datentypen interpretiert werden können, und definiert deshalb zwei Sätze von Vergleichsoperatoren. Die »normalen« Vergleichsoperatoren wie ==, != oder <= sind ausschließlich für numerische Vergleiche vorgesehen. Für String-Vergleiche werden die folgenden separaten Operatoren definiert:
- eq (»equals«) überprüft die Gleichheit zweier String-Werte, ist also immer dann wahr, wenn die beiden Strings identisch sind.
- ne (»not equals«) ist dagegen wahr, wenn die beiden Strings verschieden sind.
- lt (»less than«) ist wahr, wenn der erste String kleiner ist als der zweite, also weiter vorn im Alphabet beziehungsweise im Zeichensatz steht.
- gt (»greater than«) ist wahr, wenn der erste String größer ist als der zweite.
- le (»less than or equals«) ist wahr, wenn der erste String kleiner oder gleich dem zweiten ist.
- ge (»greater than or equals«) ist wahr, wenn der erste String größer oder gleich dem zweiten ist.
Beachten Sie, dass der Vergleich numerischer Werte mithilfe der String-Vergleichsoperatoren (wodurch sie natürlich als Strings interpretiert werden) zu anderen Ergebnissen führen kann als der numerische Vergleich derselben Werte. Beispielsweise gilt natürlich 21 < 111. Da das Zeichen »2« aber im Zeichensatz erst nach der »1« kommt, ist die Beziehung "21" lt "111" dagegen falsch.
Perl verwendet einen anderen Operator für die Verkettung von Strings als Java, nämlich den Punkt (.). Dies erspart Ihnen die Verwirrung, die durch die Verwendung von + in Java entstehen kann. Dank der Variablensubstitution wird der Operator in der Praxis aber ohnehin selten benötigt.
Genau wie die in Kapitel 7, »Linux«, vorgestellten Unix-Shells unterstützt Perl die Verwendung von HIER-Dokumenten. Dies ist nützlich, um größere Mengen Text auszugeben oder einer Variablen zuzuweisen:
print << "ENDE";
Perl
macht
Spaß!
ENDE
$zeilen = << "SCHLUSS";
Perl-Programmierung
macht Freude.
SCHLUSS
Beachten Sie, dass die Schlussmarkierung in einer eigenen Zeile stehen muss, und zwar ganz am Anfang dieser Zeile. Wenn sie die letzte Zeile im Skript bildet, müssen Sie daran denken, dahinter zu drücken, weil es sich sonst nicht um eine vollständige Zeile handelt.
Wenn die Schlussmarkierung in doppelten Anführungszeichen steht, wie in den beiden Beispielen, wird innerhalb des Textes übrigens Variablensubstitution durchgeführt.
Eine weitere interessante Besonderheit von Perl besteht darin, dass Sie logische Operatoren nicht nur für Ausdrücke verwenden können, sondern auch zur logischen Verknüpfung von Anweisungen. Bei der Verknüpfung zweier Anweisungen mithilfe von || (oder dem Synonym or) wird die zweite Anweisung nur dann ausgeführt, wenn die erste fehlschlägt. Dies liegt an der Short-Circuit-Logik der logischen Operatoren: Wie die meisten Programmiersprachen hört Perl mit der Auswertung eines logischen Operators auf, sobald das Ergebnis feststeht. Bei einer Oder-Verknüpfung steht das Ergebnis »wahr« fest, wenn der erste Ausdruck wahr ist. Dies ist bei einer erfolgreich ausgeführten Anweisung der Fall. Bekannt ist beispielsweise die folgende Formulierung zum Öffnen einer Datei:
open (FILE, "<datei.txt") or die "Kann nicht öffnen!\n";
Dies lässt sich in der Tat mit »Öffne die Datei oder stirb!« beschreiben – die Anweisung die bricht die Ausführung eines Skripts mit einer Fehlermeldung ab.
Umgekehrt wird die zweite Anweisung bei einer &&- beziehungsweise and-Verknüpfung nur dann ausgeführt, wenn die erste Erfolg hatte – andernfalls steht das Gesamtergebnis »falsch« bereits fest.
Besonderheiten bei Kontrollstrukturen
Im Großen und Ganzen funktionieren die Kontrollstrukturen in Perl genau wie in C oder Java. Allerdings existiert in Perl kein switch/case; die zusätzliche Schleifenanweisung foreach wurde dagegen bereits behandelt.
Die wichtigste Besonderheit besteht darin, dass die geschweiften Klammern bei if, while und so weiter auch dann erforderlich sind, wenn nur eine Anweisung von der Kontrollstruktur abhängen soll. Außerdem wird ein verschachteltes »else if« in Perl durch das spezielle Schlüsselwort elsif ausgedrückt.
Eine Alternative für ein if, von dem nur eine Anweisung abhängt und das kein else besitzt, ist das nachgestellte if:
print "\$a ist 0!\n" if !$a;
ist ein Synonym für folgende Fallunterscheidung:
if (!$a) {
print "\$a ist 0!\n";
}
Eine weitere Perl-Spezialität ist die zusätzliche Kontrollstruktur unless, die das Gegenteil von if darstellt und ebenfalls vor- oder nachgestellt sein kann. Die abhängigen Anweisungen werden genau dann ausgeführt, wenn die Bedingung nicht zutrifft:
die "\$b existiert nicht!\n" unless defined $b;
Die Funktion defined prüft übrigens, ob die angegebene Variable existiert.
Subroutinen
Anstelle von Funktionen können Sie in Perl sogenannte Subroutinen definieren. Sie werden durch das Schlüsselwort sub eingeleitet und durch ihren Namen aufgerufen. Das folgende einfache Beispiel zeigt, wie eine Subroutine definiert und aufgerufen wird:
tuwas; # Subroutine tuwas aufrufen
...
sub tuwas {
print "Hi! Ich tue etwas: Text ausgeben.\n";
}
Es ist vollkommen egal, an welcher Stelle Sie Subroutinen in einem Perl-Skript definieren. Allerdings ist es üblich, sie am Ende des Skripts unter dem globalen Code unterzubringen.
Subroutinen können Argumente entgegennehmen. Sämtliche übergebenen Werte befinden sich in dem speziellen Array @_, dessen einzelne Elemente Sie sinnvollerweise mithilfe von shift abtrennen sollten, weil Sie sie dadurch in der richtigen Reihenfolge einlesen können. Dazu genügt sogar die Angabe von shift ohne Argument, weil die Funktion in diesem Fall automatisch auf @_ zugreift. Das folgende Beispiel definiert eine Subroutine namens print_summe, die zwei übergebene Werte addiert und anschließend ausgibt:
sub print_summe {
$w1 = shift;
$w2 = shift;
$summe = $w1 + $w2;
print "Summe: $summe\n";
}
Diese Subroutine können Sie beispielsweise folgendermaßen aufrufen:
print_summe (3, 7);
Die folgende Subroutine erhöht jedes Element eines als Referenz übergebenen Arrays um 1:
sub list_inc {
$listref = shift;
foreach (@$listref) {
$_++;
}
}
Ein Aufruf dieser Subroutine sieht etwa so aus:
@list = qw(2 4 6 8 10);
list_inc (\@list); # @list ist nun (3, 5, 7, 9, 11)
Eine Subroutine kann übrigens auch Werte zurückgeben. Dazu wird wie in C und Java die Anweisung return verwendet.
Mit Dateien arbeiten
Perl besitzt eine besonders einfache Syntax für das Lesen und Schreiben von Dateien. Dies ist eine der wichtigsten Eigenschaften der Sprache für Systemadministratoren, die Perl gern als mächtigen Ersatz für Shell-Skripte verwenden.
Um eine Datei zu öffnen, wird die folgende Syntax verwendet:
Statt ... steht vor dem Pfad die Angabe des Zugriffsmodus: < öffnet die Datei zum Lesen, > zum Schreiben (wobei eine existierende Datei dieses Namens geleert würde) und >> zum Anhängen.
Das DATEIHANDLE ist ein Bezeichner, über den Sie auf die Datei zugreifen können. Im Gegensatz zu Variablen besitzt es kein einleitendes Zeichen und wird üblicherweise vollständig in Großbuchstaben geschrieben.
Das folgende Beispiel versucht, die Datei test.txt im aktuellen Verzeichnis zum Lesen zu öffnen, liest eine Zeile daraus und gibt diese aus. Anschließend wird die Datei mithilfe von close geschlossen.
open (FILE, "<test.txt")
or die "Kann test.txt nicht öffnen!";
$line = <FILE>;
chomp $line;
print "Gelesen: $line\n";
close FILE;
Falls Sie alle Zeilen aus der Datei lesen möchten, bietet sich die folgende Kurzfassung an:
while ($line = <FILE>) {
chomp $line;
print "Gelesen: $line\n";
}
Die Bedingung bleibt dabei automatisch wahr, solange das Dateiende noch nicht erreicht ist.
Wenn Sie eine Datei zum Schreiben (oder Anhängen) öffnen, können Sie folgendermaßen eine Zeile Text hineinschreiben:
open (FILE, ">test.txt")
or die "Kann test.txt nicht öffnen!";
print FILE "Eine Zeile Text.\n";
close FILE;
Es ist sehr wichtig, dass zwischen dem Namen des Dateihandles und dem Text, den print ausgeben soll, kein Komma, sondern nur ein Leerzeichen steht!
Auf ähnlich einfache Weise können Sie übrigens Verzeichnisinhalte lesen. Das folgende Beispiel gibt die Namen sämtlicher Dateien des aktuellen Verzeichnisses (repräsentiert durch ".") aus:
Reguläre Ausdrücke
Eine der wichtigsten Fähigkeiten von Perl ist der Umgang mit regulären Ausdrücken. Es werden erheblich mehr Optionen angeboten als bei dem Unix-Programm grep. Reguläre Ausdrücke werden in Kapitel 10, »Konzepte der Programmierung«, näher vorgestellt, deshalb sollen an dieser Stelle zwei kurze Beispiele genügen.
Um ein Muster in einem String zu finden, wird der Operator =~ verwendet:
print "Perl gefunden!" if $text =~ /perl/i;
Dies gibt »Perl gefunden!« aus, wenn in der Variablen $text die Zeichenfolge »perl« vorkommt, und zwar ohne Berücksichtigung von Groß- und Kleinschreibung (Modifikator /i).
Das folgende Beispiel ersetzt in der Variablen $text jedes Vorkommen von »Java« durch »Perl«:
$text =~ s/Java/Perl/g;
Der Operator s/// (»substitute«) ersetzt den gefundenen regulären Ausdruck durch den angegebenen String. Der Modifikator /g steht für »global« (sämtliche Vorkommen ersetzen).
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.