Perl-Programmierung/ Druckversion

Aus Wikibooks
Wechseln zu: Navigation, Suche
Perl



Wikibooks



Druckversion des Buches Perl-Programmierung
  • Dieses Buch umfasst derzeit etwa 80 DIN-A4-Seiten einschließlich Bilder (Stand: Juli 2007).
  • Wenn Sie dieses Buch drucken oder die Druckvorschau Ihres Browsers verwenden, ist diese Notiz nicht sichtbar.
  • Zum Drucken klicken Sie in der linken Menüleiste im Abschnitt „Drucken/exportieren“ auf Als PDF herunterladen.
  • Mehr Informationen über Druckversionen siehe Hilfe:Fertigstellen/ PDF-Versionen.
  • Hinweise:
    • Für einen reinen Text-Ausdruck kann man die Bilder-Darstellung im Browser deaktivieren:
      • Internet-Explorer: Extras > Internetoptionen > Erweitert > Bilder anzeigen (Häkchen entfernen und mit OK bestätigen)
      • Mozilla Firefox: Extras > Einstellungen > Inhalt > Grafiken laden (Häkchen entfernen und mit OK bestätigen)
      • Opera: Ansicht > Bilder > Keine Bilder
    • Texte, die in Klappboxen stehen, werden nicht immer ausgedruckt (abhängig von der Definition). Auf jeden Fall müssen sie ausgeklappt sein, wenn sie gedruckt werden sollen.
    • Die Funktion „Als PDF herunterladen“ kann zu Darstellungsfehlern führen.


Vorwort

Tja das Vorwort wird geschrieben wenn das Buch fertig ist.....



Inhaltsverzeichnis

Die Projektdefinition dieses Wikibuchs

Zusammenfassung des Projekts

Zielgruppe

Neueinsteiger sollen hier einen einfachen Einstieg in die Programmiersprache Perl finden. Fachleute haben andere Quellen als Nachschlagewerk (z.B. Perldoc, CPAN, Perlwiki, etc.)


Lernziele

Dieser Kurs ist dafür geschrieben, die ganze Welt der Perl-Programmierung in Theorie und Praxis vorzustellen.

Ein Motto von Perl lautet: "There is more than one way to do it". Nach der Lektüre sollte der Leser für jede denkbare Teilaufgabe mindestens einen Weg kennen, sie durchzuführen.


Buchpatenschaft / Ansprechperson

Das Buch hat zur Zeit keinen Hauptautor und kann gerne übernommen werden.

- Co-Autoren:

Sind Co-Autoren gegenwärtig erwünscht?

Co-Autoren sind ausdrücklich erwünscht.


Richtlinien für Co-Autoren:

Da es in Perl durch seine Möglichkeiten der Syntaxgestaltung sehr leicht möglich ist, extrem unleserlichen Code zu produzieren, sollte eine gewisse Einheitlichkeit an den Tag gelegt werden, um es dem Leser einfacher zu machen, den Quelltext zu verstehen. Dies gilt für die Art der Klammerung, Variablendeklarationen, usw. Viele dieser Richtlinien stammen aus dem Buch "Perl Best Practices" von Damian Conway und gelten als Standards für guten Perl-Code. Natürlich steht es jedem frei, sich diese Regeln anzueignen, aber wenigstens im Laufe dieses Buches sollten sie verwendet werden.

Klammerung

Die Richtlinie zur Klammerung innerhalb des Buches ist der K&R-Stil. Er hat gegenüber anderen Klammerungsstilen den Vorteil, dass er eine Zeile spart, dabei die Lesbarkeit der Schleife oder Anweisung jedoch nicht beeinträchtigt.

Beispiel ( K&R-Stil ):

for (1 .. 10) {
    print $_, "\n";
}

Im Gegensatz zu diesem Beispiel, hier ein Beispiel mit dem BSD-Stil:

Beispiel ( BSD-Stil ):

for (1 .. 10)
{
    print $_, "\n";
}

Zwar ist der Code hier mindestens gleich gut zu lesen, aber er braucht eben eine Zeile mehr. Und Zeilen sind kostbar. :) Diese Richtlinie gilt auch bei der Deklaration von Listen und Hashes.

Beispiel-Deklaration ( K&R-Stil ):

my @list = (
    'blubb',
    'blibb',
    'blebb'
);

my %hash = (
    'id1'  =>  'name1',
    'id2'  =>  'name2',
    'id3'  =>  'name3',
    'id4'  =>  'name4'
);

Bei kurzen Listen ist dies natürlich nicht erforderlich, aber sobald eine Liste die kritische Masse erreicht hat, in der sie nicht mehr in eine Zeile passt ( > 80 Zeichen ) sollte sie in der oben angeführten Form geschrieben werden um es dem Leser verständlicher zu machen.

Einrückungen

Generell sollte für jede Stufe eine Einrückung von 4 Leerzeichen verwendet werden. Das ist der Kompromiss zwischen den 8 und den 2 Leerzeichen, die sonst oft Anwendungen finden. Damit hat man genug Übersicht um sich zurechtzufinden und muss trotzdem kein Augentennis spielen wenn man zwischen den Zeilen herumspringt.

Beispiel:

if (1 == 1) {
    print "1 ist 1", "\n";
}

Operatoren und Zuweisungen

Um eine Zuweisung übersichtlich zu halten, ist es zu begrüßen, wenn sie den Elementen der Zuweisung ein wenig Platz lassen. So ist folgende Zuweisung

my $var=(1+3/5)*(6-3);

erheblich schwerer zu lesen als

my $var = (1 + 3 / 5) * (6 - 3);

Zwar benötigt man so mehr Platz, aber um die Übersichtlichkeit zu gewähren, ist das ein verschmerzliches Übel.

use strict; use warnings;

Dieses Buch richtet sich an Anfänger. Gerade diesen sollte man zeigen, wie man gefährliches Perl vermeidet. Dazu zählt der Einsatz von Warnungen und 'strictures'.

Die beiden Pragmas use strict; und use warnings; sollten am Anfang eines jeden Beispiels stehen, das eigenständig lauffähig ist. Bei nicht eigenständigen Code-Fragmenten sind sie nicht unbedingt nötig, aber diese sollten durch Verwendung von "..." oder explizit durch Perl-Kommentare als unvollständig gekennzeichnet werden. Darüber hinaus sollten Code-Fragmente nur selten verwendet werden, der Schwerpunkt sollte auf vollständigen Programmen liegen.

perl -w ist antik und soll vermieden werden, s. perllexwarn, What's wrong with -w and $^W

Formatierungen

  • Bei Codestücken, die code-zeilen-nummerierung mitnehmen, da es dann leichter wird sich zurechzufinden, wenn man sich auf etwas bezieht ( nur wenns längere Beispiele sind, bei Einzeilern ist das sinnfrei ;) )
  • Falls im Text Funktionen/Schlüsselwörter angesprochen werden, diese so herauszuheben: <code>while</code> -> while um sie leichter erkennbar zu machen
  • Variablen, die im Beispiel vorkommen und im Text erläutert werden fett zu halten: '''$testvar''' -> $testvar
  • Im Text erwähnte CPAN-Module bitte als Links auf die CPAN Seite formatieren.

Projektumfang und Abgrenzung zu anderen Wikibooks

Themenbeschreibung

Aufbau und Bearbeitungsstatus des Buches

Für Neugierige hier zuerst ein kurzer Überblick über den Aufbau. Er ist auch für Praktiker und Fortgeschrittene nützlich, damit sie erfahren, welche Kapitel sie überspringen können.

Die ersten Kapitel behandeln Perl theoretisch. Mit wichtigen Grundinformationen beginnend wird es immer spezifischer und zum Ende hin auch ein wenig philosophisch, so dass jeder für sich entscheiden kann, wann er sich bereit für die Praxis fühlt und den Rest dieses Kapitels überspringen möchte.

Der zweite Abschnitt ist der Grundkurs, in dem es um Variablen, Funktionen, Schleifen und etwas Spielerei mit Dateien und Texten geht.

Formales 00% fertig

Vorwort 00% fertig

Einführung 00% fertig

Kurzvorstellung 00% fertig
Das Richtige für mich? 00% fertig
Eintauchen in die Perlenwelt 00% fertig
Geschichte einer Skriptsprache 00% fertig
Larry und die Perl-Kultur 00% fertig

Der Einstieg 00% fertig

„Hello World!“ 00% fertig
Variablen 00% fertig
Variablenklassifizierung und Fallbeispiele 00% fertig
Spezialvariablen 00% fertig
Einfache Ein-/Ausgabe 00% fertig
Dateien 00% fertig
Operatoren 00% fertig
Kontrollstrukturen 00% fertig
Subroutinen 00% fertig

Fortgeschrittene Themen 00% fertig

Programmierstil und -struktur 00% fertig
Gültigkeitsbereich von Variablen 10% fertig
Reguläre Ausdrücke 30% fertig
Objektorientiert Programmieren in Perl 00% fertig
Vordefinierte Variablen 00% fertig

Perl-Schnittstellen 00% fertig

GUI in Perl 00% fertig
Perl/TK 00% fertig
Perl/QT 00% fertig
Perl/GTK 00% fertig
Perl/wxWidgets 00% fertig
Web-Entwicklung in Perl 00% fertig
CGI 00% fertig
mod_perl: Perl-Beschleunigung unter Apache 00% fertig
DBI: Datenbankzugriffe in Perl 00% fertig
Benutzen der CPAN-Bibliotheken 00% fertig

Beispiele

Einfache Beispiele für den Einstieg 00% fertig

Anhänge 00% fertig

Funktionsreferenz 00% fertig
Nützliche Module 00% fertig
Schnellreferenz 00% fertig
Webseiten und mehr 00% fertig
Buchtipps 00% fertig
Glossar 00% fertig
Installation 00% fertig

Wikibooks.org

Perl-Programmierung/ Druckversion 00% fertig



Liste der verwendeten Vorlagen: Perl-Programmierung: Vorlagen



Das Wikibuch: Perl Programmierung

Kurzvorstellung

Perl ist eine von Larry Wall entwickelte Programmiersprache, die erstmals (Version 1.0) am 18. Dezember 1987 im Usenet veröffentlicht wurde. Larry Wall entwickelte Perl damals, um sich seine Arbeit als Betreuer eines USA-weit verstreuten Computernetzes zu erleichtern. Er verband dabei Ausdrucksweisen und Fähigkeiten von Programmiersprachen wie C, BASIC, Pascal und Ada. Er verwendete auch bekannte UNIX-Werkzeuge wie sed, awk, shell und grep als Vorlage für Perl-Befehle. Dabei orientierte er sich weder am Ideal optischer Schönheit und Eindeutigkeit, wie es die verwandte Sprache Python tut, noch an strenger Logik und Einfachheit wie beispielsweise LISP, sondern am Reichtum menschlicher Lese- und Denkgewohnheiten. Laut Larry Wall wurde Perl dafür entworfen, um möglichst frei, individuell und schnell die eigenen Ideen umsetzen zu können. Ein Perl-Programm ist auch so wie es geschrieben wurde sofort startbereit, benötigt aber einen Interpreter, um ausgeführt zu werden. Dieser Perl-Interpreter ist für jedes gängige Betriebssystem frei erhältlich und wird weiterhin vom Erfinder und vielen Freiwilligen gepflegt und weiterentwickelt.

Besonderheiten des Sprachkonzepts von Perl

Sprachen wurden von Menschen zum Nutzen von Menschen eingeführt. Da Perl von einem (sozusagen) Gelegenheitslinguisten entworfen wurde, orientiert sich die Sprache sehr nahe an der natürlichen Sprache. Selbstverständlich gibt es hierfür verschiedenste Betrachtungswinkel. Dies zu erläutern wäre zu kompliziert, deshalb sei gesagt, dass bei Perl einfache Dinge auch einfach bleiben sollen und kompliziertes immer noch möglich sein sollte. Diese Forderung, die wir an diese Sprache stellen, ist klar und eindeutig. Allerdings scheitern genau an diesen Punkten sehr viele andere Programmiersprachen, Perl nicht.

Natürliche Sprachen ändern sich stetig. Dies liegt einerseits daran, dass wir Menschen lebendig sind und nicht wollen, dass uns etwas diktiert oder absolut aufgezwungen wird, andererseits daran, dass Menschen schon immer kreativ und einfallsreich waren. Perl wurde nun extra so entwickelt, dass es wachsen kann, und somit der "Wortschatz" nicht immer auf dem gleichen Stand bleibt. Und ja, es ist gewachsen. Das Kamel (Logo von Perl) ist und bleibt eigenständig und absolut durchsetzungsfähig. Zudem sagt man, dass ein Kamel nicht gerade gut riecht; Perl wurde auch nie so entwickelt, dass es "gut riecht".

Perl ist sogar einigermaßen intelligent; es hört zu und versucht zu begreifen, was Sie machen wollen. Ein Beispiel: Wenn ich das Wort "dog" sage, dann hören Sie es als ein Substantiv. Ich kann das Wort aber auch auf andere Weise verwenden. Das heißt, ein Substantiv kann auch als Verb oder Adjektiv oder Adverb fungieren, wenn es der Zusammenhang verlangt. Perl beurteilt Wörter auch aus dem Kontext heraus. Wie es das macht, werden Sie später noch feststellen können. (Wenn Sie nicht gerade Unsinn reden, wird Perl auch etwas tun, und wenn das, was Sie sagen, auch nur irgendwie verständlich ist, dann wird es Perl auch richtig tun). Die meisten Programiersprachen treffen Unterscheidungen dieser Art meist durch Deklaration von Variablen. Perl tut sich hier einfacher: Man braucht die Variablen nicht explizit deklarieren, sondern Perl unterscheidet hier selbstständig.

Aber dennoch ist Perl eine künstliche Sprache. Sie hat einen bestimmten Wortschatz und eine bestimmte Syntax, die sich nicht mehr ändern wird. Außer dass hin und wieder mal etwas Neues dazukommen wird, wird sich hier nichts mehr ändern. Und die Sprache ist eindeutig; jeder auf der Welt, der Perl kann, kann auch einzelne Perl-Scripte begreifen und verstehen. Denn die Sprache wird in Indien genauso geschrieben wie in Deutschland oder Amerika.


Das Richtige für mich? - Stärken, Schwächen und Alternativen zu Perl

Die Wahl der Sprache

Damit während des ganzen Kurses Ihre Freude an Perl anhält und Sie ehrlich unsere Begeisterung für Perl teilen können, möchten wir Ihnen einige Empfehlungen nahelegen, wann Perl wirklich eine gute Wahl ist, oder ob Sie vielleicht besser eine andere Sprache lernen sollten. Orientieren Sie sich am besten an den fettgedruckten Wörtern, die Ihre Lage am besten umschreiben. Falls Sie sich sicher sind, können Sie dieses Kapitel auch gerne überspringen.

Nach Erfahrung der Benutzer

  • Anfänger Entgegen manchen Vorurteilen ist Perl für absolute Anfänger sehr zu empfehlen. Bereits ein einzelner Befehl ist schon ein lauffähiges Programm und ein erster Erfolg. Mit einigen wenigen Grundtechniken lässt sich viel erreichen, und der Benutzer kann selbst bestimmen, wann er welche fortgeschrittene Technik erlernt.
  • Enthusiast Wer in der Freizeit für den Eigenbedarf und den Spaß an der Sache programmiert, ist mit Perl gut beraten. Es führt schnell zu Ergebnissen. In fast allen Bereichen gibt es viele freie, fertige Module, und man kann sich in Perl nach eigenen Vorstellungen austoben wie in kaum einer anderen Sprache. Wer seine Fenster und Dialoge mit wenigen Klicks "zusammenschieben" möchte, kann das auch mit dem gut unterstützten TKinter und einer professionellen IDE wie Komodo. Eine populäre und sehr ausgereifte Alternative von Borland, die auf der Sprache Pascal basiert, ist auf diesem Gebiet Delphi und unter Linux Kylix. Auch hier findet man einfaches Arbeiten, freie Komponenten und viele Gleichgesinnte. Der Kern von Object Pascal wird aber leider schon längere Zeit nicht mehr weiterentwickelt.
  • Berufsprogrammierer Wer Geld verdienen will, sollte etwas wie C, C++, C#, Visual Basic und Java können. Auch wenn es zunehmend Perl-Jobs gibt, sind diese noch nicht so häufig und sind oft auf den Internetseiten-Bereich beschränkt. Doch es ist abzusehen, dass Perl, aber auch Python, TCL und Ruby, wegen seiner hohen Produktivität und der eingebauten Unabhängigkeit vom Betriebssystem mehr Möglichkeiten offen stehen werden.
  • Umsteiger Wer bereits Erfahrung mit einer Sprache wie C, Java, Basic, Pascal, oder den UNIX-Werkzeugen wie sed, awk, grep usw. hat, wird sich schnell in Perl einfinden, weil er nicht nur im gleichen Stil weiterschreiben kann, sondern auch zum großen Teil sogar die Schreibweisen der Befehle übernommen wurden.
  • Studenten Um seinen Horizont zu erweitern, neue und frische Ideen zu sammeln, ist Perl nicht die schlechteste Wahl. Es unterstützt die meisten der heute üblichen Programmierstile und besitzt viele eigenwillige Lösungen. Die neuesten Impulse kommen aber von Sprachen wie Haskell, Cecil, Dylan, Comega, Heron und Nice. Nicht jede dieser Sprachen ist rein experimentell, aber meist gibt es dort, im Gegensatz zu Perl, wenig unterstützende Infrastruktur an Programmierwerkzeugen, Bibliotheken und Internetforen.


Nach Anwendungsgebiet

  • Webdesigner Bei der Erstellung von größeren Internetseiten ist mittlerweile das Perl recht ähnliche PHP oder Microsofts Alternative ASP gebräuchlicher. Wenige Zeilen PHP lassen sich lesbarer in den HTML-Quellcode einbinden als Perl, andererseits bietet das wesentlich ältere Perl hier immer noch mehr Möglichkeiten für anspruchsvolle Programmierer. Zudem gibt es mittlerweile für Perl diverse Templating-Systeme, die das saubere Trennen von Programmier- und HTML-Code ermöglichen. Das mod_perl Modul des häufig verwendeten Apache-Webservers und das Active State plex modul im Microsoft IIS Server erlauben es, mit Perl anspruchsvolle und schnelle Webportale und sogar effiziente Vielrechner-Systeme zu erstellen.
  • Hardwaretüftler Wer Betriebssysteme, Treiber oder sonstige Software schreiben will, die direkt mit der Hardware kommuniziert oder einfach nur sehr schnell sein soll, benutzt am besten Assembler wie NASM, MASM, TASM oder hardwarenahe Hochsprachen wie C.
  • Applikationsentwickler Perl kann man auch in eigene Programme einbauen, um es dem Benutzer zu ermöglichen, mit Erweiterungen, sogenannten Plugins oder Extensions, Funktionen hinzuzufügen, an die man selbst nicht dachte. Dafür eignen sich aber auch andere Sprachen wie Tcl, Python oder als neuere und besonders sparsame Möglichkeit: Lua.
  • Bioinformatiker. Im Bereich der Bioinformatik ist Perl sogar so populär, dass eigens ein Buch für diesen Teilbereich geschrieben wurde. Beginning Perl for Bioinformatics: http://www.oreilly.com/catalog/begperlbio/
  • Administratoren Auf Unix-artigen Betriebssystemen ist Perl so weit verbreitet, dass es als Standard-Tool installiert ist. Durch die starke Unterstützung von regulären Ausdrücken eignet sich Perl ideal um Log-Dateien auszuwerten, und grafisch als Statistik oder als eMail zu versenden. Die Möglichkeit Daemons zu schreiben, Prozesse zu automatisieren, Programme zusammen zu führen, die hohe Anzahl der CPAN-Modulen, die Portierung auf fast jeder Architektur und Betriebssystem, und vor allem die bereits Vorhandene Installation von Perl machen es zum Idealen Tool eines Administrators. Einmal geschriebene Skripte können flexibel ohne Anpassung auf unterschiedlicher Hardware sowie Betriebssystemen verwendet werden.

Schlussbemerkung

Die Wahl der Programmiersprache hat natürlich auch immer etwas mit persönlichen Vorlieben und dem eigenen Charakter zu tun. Wer feststellt, dass Perl in der Sache gut ist, aber sich an einzelnen Regelungen stößt, könnte Ruby ausprobieren, das Perl in vielem sehr ähnlich ist, aber wesentlich strikter an der objektorientierten Programmierung ausgerichtet ist oder  Python, das den Benutzer stärker zu Übersichtlichkeit und Eindeutigkeit anleitet. Wer sich bis jetzt nicht für eine Sprache entscheiden konnte, hat auch die Möglichkeit, das allgemeine Wiki-Buch über Programmieren zu lesen.


Eintauchen in die Perlenwelt

Nachdem nun auf Historie und das Perl-Umfeld, die Einordnung von Perl in die Informatik und Programmierung eingegangen wurde, sollen nochmals grundlegende Eigenschaften und Fähigkeiten stichwortartig aufgezählt und kurz in jeweils ein bis zwei Sätzen erklärt werden, bevor der eigentliche Perl-Kurs anfängt.

  • Alternative Ausdrucksmöglichkeiten
Es gibt alternative Ausdrucksmöglichkeiten gleicher Algorithmendarstellungen. Dadurch kann eine für den Entwickler geeignete leicht lesbare Form fallbasiert verwendet werden.
  • Objektorientierung
Gerade die in Perl implementierte, extrem flexible Objektorientierung und die Möglichkeit Variablen und Handler zu definieren, die einfache Möglichkeit Operatoren zu überladen usw. lassen einem sehr viele Freiheiten. Perl kann als eine objektorientierte Sprache eingesetzt werden.
  • funktionale Programmierung
In Perl sind Funktionen „Bürger erster Klasse“. Unter anderem bedeutet dies, dass Funktionen zur Laufzeit erzeugt und an andere Funktionen als Argumente übergeben werden können. Dies ermöglicht funktionale Programmierung – die Erstellung von Programmen, deren Ablauf nicht durch die Manipulation und Abfrage von Variablen gesteuert wird, sondern die durch Aufruf von Funktionen ihren Zweck erfüllen. Perl kann als eine funktionale Sprache eingesetzt werden.
  • Interpreter-Ähnlichkeit, Byte-Code-Interpreter und Compiler
Perl-Quelltexte können – ähnlich einer Interpreter-Sprache – direkt gestartet werden. Obwohl Perl die meisten der Bequemlichkeiten einer interpretierten Sprache hat, interpretiert es den Quellcode nicht streng Zeile um Zeile. Das gesamte Programm wird, wenn es aufgerufen wird, zuerst in Bytecode übersetzt (ziemlich ähnlich der Programmiersprache Java), optimiert und dann ausgeführt. Es ist möglich, die Übersetzung in Bytecode schon früher durchzuführen, um beim Programmstart Zeit zu sparen; der Interpreter wird aber immer noch benötigt, um diesen Bytecode auszuführen. Auch sind bereits Möglichkeiten geschaffen, die Perl-Quelltexte zu kompilieren, so dass direkt ausführbarer Binärcode vorliegt.

Perl ist freie Software und unter der Artistic License und der GNU General Public License erhältlich. Erhältlich für die meisten Betriebssysteme, wird Perl am häufigsten auf Unix- oder Unix-ähnlichen Systemen genutzt, während die Beliebtheit auf Microsoft Windows Systemen noch steigt. Perl hat auch heute viele Anwendungsgebiete. Ein Beispiel für die Nutzung von Perl: Die Wikipedia-Software war bis zum Januar 2001 selbst ein CGI-Skript, das in Perl geschrieben wurde. Ein weiteres Beispiel ist das bekannte Informationsportal Slashdot, welches mithilfe der Perl-basierten Slashcode-Software läuft. Im Web wird Perl oft zusammen mit dem Apache-Webserver und dessen Modul mod_perl genutzt.


Geschichte einer Skriptsprache

Ursprünglich waren Skripte Textdateien mit Befehlen, die man auch in die Kommandozeile (System-Shell) eingeben könnte. Diese Skripte ließen sich vergleichsweise schnell schreiben und es war damit möglich, Befehle des Betriebssystems mit Programmaufrufen zu kombinieren, um so komplexere Aufgaben dem Computer zu überlassen, ohne in langer Arbeit ein neues Programm zu schreiben. Die Kommandozeileninterpreter, die diese Skripte ausführten, hatten aber wesentlich geringere Fähigkeiten, Daten zwischenzuspeichern oder den Ablauf zu regeln als eine Programmiersprache wie C. Außerdem konnte man in Skripten die Daten nur wie durch ein Nadelöhr von einem Programm hinaus und zum nächsten Programm hinein leiten.

Larry Walls Reaktion auf diese Situation war, einen erweiterten Kommandozeileninterpreter zu schreiben, der nicht nur fast den gesamten Sprachschatz von C beherrscht, sondern auch viele der kleinen nützlichen Helferlein kopiert, besonders sed, awk und grep, die die Kommandozeile des Betriebssystems UNIX so mächtig machen. Damit lassen sich viel mächtigere Skripte schreiben, die Textdateien durchsuchen und die von anderen Programmen ausgespuckten Ergebnisse sortieren und aufbereiten können. Aus diesem Grund nannte man PERL auch eine: 'Practical Extraction and Report Language' (praktische Auszugs- und Berichtsprache), was aber nur ein Backronym ist, weil die ursprüngliche Bedeutung des Namens Perl eine andere ist (siehe nächstes Kapitel). Ein anderes Backronym, das von Larry ebenso für „offiziell“ erklärt wurde, ist: 'Pathologically Eclectic Rubbish Lister' (krankhaft ausufernder Auflister von Blödsinn), denn mit Perl kann man wirklich sehr sehr unverständliche Programme verfassen. Warum das so ist, erklär' ich auch im nächsten Kapitel.

Mit der Zeit lernte Perl auch mit binären Daten umzugehen und viele weitere nützliche Dinge, die überall abgeschaut wurden. Besonders mit seiner fünften Version veränderte sich Perl zu einer „richtigen“ Programmiersprache, als nicht nur die objektorientierte Programmierung eingeführt wurde, sondern auch die diesem Konzept zugrunde liegenden Module. Diese Module, die Perl meist um eine wertvolle Fähigkeit ergänzen, zum Beispiel graphische Ausgabe, Herunterladen von Webseiten oder Steuern von Robotern, findet man in großer Anzahl und in oft sehr guter Qualität in dem zentralen Archiv namens CPAN. Kritiker und Anhänger von Perl sind sich zumindest darin einig, dass der Erfolg von Perl heute zu einem bedeutenden Teil am CPAN liegt, mit dessen Hilfe man auch anspruchsvollere Aufgaben in nur wenigen Zeilen Quellcode lösen kann, indem man mehrere fertige Module kombiniert.

Das entspricht eigentlich immer noch dem ursprünglichen Prinzip des „Skriptens“, obwohl sich dieser Begriff erweitert hat auf eine Bedeutung, die man etwa mit kürzeres, schnelleres, komprimiertes Programmieren übersetzen kann. Neben Perl entstanden nämlich noch seit den 80er Jahren eine Reihe weiterer „Skriptsprachen“ wie Ruby, Python, PHP, Tcl, Visual Basic Script, die dem Programmierer einiges an Arbeit abnehmen oder vereinfachen. Manche Autoren sehen darin eine „nächste“ oder „höhere“ Generation an Computersprachen, die sich noch näher an den Bedürfnissen der Programmierer orientieren und noch weniger an den konkreten Fähigkeiten einer Maschine.

Auch eine wichtige Gemeinsamkeit dieser Skriptsprachen ist, dass es Interpretersprachen sind. Das sind Sprachen, bei denen das Programm immer noch einen Interpreter benötigt, der den Quellcode ausführt. Ein Vorteil daran ist, dass man keinen weiteren Aufwand treibt, um ein lauffähiges Programm zu bekommen. Nur den Quellcode schreiben und das Programm ist fertig. Es läuft sogar meist unverändert auch unter anderen Betriebssystemen. Man braucht dafür nur einen neuen, unter diesem Betriebssystem lauffähigen Interpreter. Dieser Vorteil wurde aber lange Zeit wenig genutzt, weil diese Interpreter zu langsam waren, was aber mit den hohen Geschwindigkeiten neuerer Hardware ausgeglichen wird. Außerdem erkannte man mittlerweile, dass interpretierte Programme viel besser optimiert werden können als kompilierte, weil zum Zeitpunkt der Ausführung sehr viel mehr über den aktuellen Computer bekannt ist als bei der Programmierung.


Larry und die Perl-Kultur

Was ist perlish?

Neben der ganzen Logik und der Technik übersehe bitte niemand, dass Programmieren für manche Menschen Begeisterung, Leidenschaft und Berufung ist. Nicht wenige davon halten Perl für eine Lebensphilosophie, eine Art zu denken und zu handeln, die man auf alles übertragen kann. Nach dieser Einstellung wird „perlish“ genannt, was für bequem, cool, eigenwillig, treffend oder clever gehalten wird. Larry Wall hat von Anfang an mit witzigen und spitzfindigen Bemerkungen, Vorträgen und Büchern darüber referiert, wofür Perl steht und was perlish ist. Dabei prägte er die folgenden Abkürzungen und Slogans, welche die Perl-Philosophie wiedergeben sollen.

Leitsprüche

  • TIMTOWTDI wird auch timtoday ausgesprochen, steht aber für "There Is More Than One Way To Do It", zu deutsch: „Es gibt mehrere Wege, etwas zu tun.“ Damit ist gesagt, dass es in Perl mit Absicht für jede Aufgabe viele Wege gibt, sie zu lösen, und dass die Sprache es dem Programmierer überlässt, welchen Weg er wählt. Perl wird von Larry Wall als bescheidener Diener gesehen, der möglichst vielen unterschiedlichen Menschen behilflich sein will, ohne ihre Freiheit einzuschränken.
  • „Make easy jobs simple and the hard possible.“ deutsch: „Lass die einfachen Aufgaben einfach und mach die schweren Aufgaben lösbar.“ Darin stecken eigentlich 3 Aussagen.
  1. Für einfache Dinge braucht man in Perl nichts anzumelden oder vorzubereiten. Nur die einfache Anweisung und Perl tut, was es soll.
  2. Perl will die Möglichkeit bieten, den Quellcode großer und komplexer Programme beherrschbar zu gestalten.
  3. Es wird versucht, beide Prinzipien zu harmonisieren, damit beides parallel mit einer Sprache erreicht wird.
  • Eine Programmiersprache kann, wie eine natürliche Sprache auch, verschieden interpretierbar sein. Für eine Programmiersprache gilt aber, dass sie keine Mehrdeutigkeit erlaubt. Es muss also eine eindeutige Implementierung geben. Daher wurde bei der Umsetzung der Sprache dieses Prinzip verfolgt: Perl verhält sich so, wie es der Programmierer am ehesten erwartet.
  • „Postmodernism“: Larry Wall nennt Perl auch die erste postmoderne Programmiersprache. Dahinter steht der Gedanke von der Befreiung von Dogmen, die oftmals eine Ära kennzeichnen. Techniken wie z.B. objektorientierte Programmierung sollten nämlich nicht zu Dogmen überhöht werden, die blind befolgt werden, weil es gerade schick ist. Jeder sollte das verwenden, was für ihn am nützlichsten ist oder was ihm am meisten Freude bereitet.

Es geht bei Perl also sehr um die Freiheit des Programmierers.




Der Einstieg

„Hello World!“

Wer das Pech hat, vor einem Rechner ohne Perl zu sitzen, und niemanden gefunden hat, der ihm das abnehmen kann, sollte einen Blick in unsere Installationsanleitung werfen.

Traditionsgemäß ist das erste Programm, das man in einer neuen Programmiersprache schreibt, eines, das 'Hello World!' ausgibt.

Hello World

hello.pl:

print "Hello World!\n";

Das typische Einstiegsbeispiel einer Programmiersprache, das Ausgeben von "Hello World!" auf dem Bildschirm, beschränkt sich bei Perl auf eine einzige Zeile. Sie enthält die Anweisung, einen Text auszugeben und den Text selbst, gefolgt von einem Semikolon, welches das Ende der Anweisung anzeigt. Texte können in Perl sowohl in einfache (') oder doppelte Anführungszeichen (") eingeschlossen werden. Hier in diesem Beispiel werden doppelte Anführungszeichen verwendet, dadurch werden bestimmte Zeichenfolgen durch Steuerzeichen ersetzt. In diesem Fall wird "Hello World!" als Text interpretiert, der eins zu eins auf dem Bildschirm ausgegeben wird. Das \n ist das Zeichen für einen Zeilenumbruch.

Auf unixartigen Systemen gibt es zwei Konzepte, das Programm ablaufen zu lassen.

  • Am einfachsten ist es, den Perl-Interpreter mit einem Kommando aufzurufen, und ihm die Quellcode-Datei als Parameter zu übergeben:
$ perl hello.pl
  • Am häufigsten wird meist zusätzlich zu Beginn des Quelltextes die sogenannte shebang-Zeile eingegeben. Sie gibt an, mit welchem Interpreter-Programm der nachfolgende Quellcode ausgeführt werden soll. Bei einer Standardinstallation liegt der perl-Interpreter bei Unix-Systemen im Verzeichnis /usr/bin, die Shebang-Zeile lautet also
#!/usr/bin/perl

Sollte sich der Perl-Interpreter woanders befinden, läßt er sich mit dem Kommando "which perl" lokalisieren.

Damit haben wir nun folgenden Code:

hello.pl:

#!/usr/bin/perl
print "Hello World!\n";


Das reicht aber noch nicht: Zusätzlich müssen wir die Quellcodedatei mit "chmod +x hello.pl" ausführbar machen. Das erlaubt uns den Programmstart mit:

$ ./hello.pl


Unter Windows hat die shebang-Zeile keine Funktion, schadet jedoch auch nicht. Unter Windows sollte unsere Komandozeile daher entsprechend anders aussehen:

C:\Perl\scripts> perl hello.pl
  • Ändern Sie das Programm so ab, dass es nicht mehr die Welt, sondern Sie begrüsst.
  • Ändern Sie das Programm so ab, dass es Sie nach der Begrüßung in der nächsten Zeile fragt, wie es Ihnen geht. Die Ausgabe sollte in etwa so aussehen:
Hallo Ihr_Name!
Wie geht es Ihnen?
  • Spielen Sie ein wenig mit dem Sonderzeichen \n herum. Was passiert, wenn Sie es weglassen oder verdoppeln?

Hinweis: Denken Sie an das Semikolon, wenn Sie eine neue print-Anweisung einfügen.

Dokumentation

Perl ist mit einer Fülle von Dokumentation ausgestattet. Diese ist über viele Handbuchseiten (engl. manual pages, kurz man pages) verstreut. Eine Übersicht über die vorhandenen Handbuchseiten kann man sich mit

man perl

anzeigen lassen.

man ist ein Unix-Befehl. Wenn Sie kein Unix oder ein ähnliches System wie Linux und BSD einsetzen, dann ist dieser Befehl auf Ihrem System möglicherweise nicht verfügbar.

Die Perl-Dokumentation ist auch im Web unter perldoc.perl.org erhältlich.

In diesem Wikibuch werden Sie an verschiedenen Stellen dazu aufgefordert, Informationen auf einer Handbuchseite nachzuschlagen. Damit ist dann stets gemeint, die betreffende Seite mit man oder im Web unter perldoc.perl.org zu betrachten.

Die in Perl eingebauten Funktionen sind auf der Handbuchseite perlfunc erläutert. Diese Handbuchseite ist lang und in der Regel müssen Sie etwas blättern, bis Sie die betreffende Funktion gefunden haben. Daher gibt es dafür ein Abkürzung:

 perldoc -f Funktionsname

zeigt Ihnen die Dokumentation zu genau dieser einen Funktion an.

  • Schlagen Sie die Handbuchseite zu man nach.
  • Lesen Sie nach, wie die Funktion print funktioniert. (Sie müssen noch nicht alles verstehen.) Hinweis: Denken Sie daran, dass Sie Dokumentation zu einer Funktion nicht nur auf eine Art nachschlagen können. (TIMTOWTDI).
  • Schlagen Sie mit perldoc im Katalog der häufig gestellten Fragen nach, welche Perl-Version Sie einsetzen sollten. Gibt es eine eindeutige Antwort? Welche Version setzen Sie ein?

Sicherheitsgurt anlegen

In Perl ist es sehr einfach, sehr kryptisch anmutenden Code zu schreiben, da praktisch alle Sonderzeichen mit Bedeutungen belegt sind und die Sprache Perl selbst viele Abkürzungen und implizites Verhalten bereit stellt.

Es wird im Allgemeinen als guter Stil angesehen, nicht alle Möglichkeiten in Perl auszureizen, da sich sonst leicht Fehler einschleichen und unwartbarer Code entsteht.

Einige sprachliche Möglichkeiten, die sich über die Jahre als problematisch erwiesen haben, kann man mit der Anweisung use strict; unterdrücken. Der Perlcompiler gibt dann bei der Compilierung eine entsprechende Warnung aus.

Eine weitere Anweisung hilft bei der Entwicklung „sauberen“ Codes. Die Perlsyntax erlaubt Ausdrücke, deren Auswertung nicht immer das bewirkt, was der Programmierer erwünscht. Perl selbst „kennt“ einige dieser Ausdrücke und kann sich selbst auffordern, bei Verwendung dieser Ausdrücke Warnungen auszugeben. Beispiel für einen solche Ausdruck ist die Addition einer Zahl und einer Zeichenkette. Obwohl dies von der Syntax her gültiges Perl ist, kann über die Sinnhaftigkeit zumindest gestritten werden. Die Anweisung use warnings; führt zur Ausgabe der Warnungen.

Die beiden angesprochenen use-Anweisungen sollten zu Beginn eines jeden Perlskripts stehen, da sie nicht nur bei der Fehlersuche helfen, sondern den Programmierer auch dabei unterstützen, Fehler zu vermeiden.

Um diese beiden Anweisungen erweitert sieht das erste Perlskript dann wie folgt aus:

hello.pl:

#!/usr/bin/perl

use strict;
use warnings;

print "Hello World!\n";
Querverweise: Siehe auch Guter Stil (in Stil und Struktur)


Variablen

Perl-Variablen

Unter einer Variable versteht man ganz allgemein einen Bezeichner für Daten. Früher konnte man davon sprechen, dass ein Bereich des Hauptspeichers mit dem Variablennamen identifiziert wurde. Im Gegensatz dazu existiert bei Perl die Möglichkeit auch eine Datei, ein Feld in einer Exceltabelle, eine Webseite auf einem Computer am anderen Ende des Globus und viele andere Vorkommen von Daten wie eine Variable zu behandeln. Im Normalfall ist aber auch in Perl eine Variable ein Bezeichner für Daten, die im Hauptspeicher des Rechners liegen. Perl übernimmt dabei die komplette Speicherverwaltung. Es verwendet ein für die Programmierer sehr bequemes System mit einem Zähler für jeden gespeicherten Wert. Mit diesem Zähler kann Perl feststellen, ob in dem Programm noch ein Verweis auf diesen Wert existiert. Variablen können in Perl fast beliebig groß sein. Von undef, dem Standardwert von Perl für eine Variable ohne Inhalt und den vielen Gigabyte Speicher, welche das jeweilige System Perl zur Verfügung stellen kann.

Skalare Variablen

Skalare Variablen sind in Perl-Code leicht erkennbar durch das vorangestellte Dollar-Zeichen ($). Sie können fast jede Art von Daten speichern. Mit dem Zuweisungsoperator = kann ihnen ein Wert zugewiesen werden. In Skalaren werden auch Referenzen (Verweise auf andere Variablen; vergleichbar mit Zeigern in anderen Programmiersprachen) und Objekte gespeichert.

Zahlen

$var = 50;     # ganze Zahl
$var = 0.01;   # Fließkommazahl
$var = 1e2;    # wissenschaftliche Notation – dasselbe wie 100
$var = 1e-2;   # wie 0.01

In Perl als Skriptsprache muss, anders als in anderen, nicht-interpretierten Sprachen wie z. B. C, nicht angegeben werden, ob eine Variable eine ganze Zahl, Fließkommazahl, oder anderes enthält. Perl übernimmt die Bestimmung des Datentyps für uns, abhängig von dem jeweiligen Umfeld, in dem die Variable verwendet wird.

Beispiel
#!/usr/bin/perl

use strict;
use warnings; 

my $a = 2;
my $b = 3;
print "$a + $b = ", $a + $b, "\n";

Die Ausgabe des Programmes:

2 + 3 = 5

Erklärung: Die Shebang-Zeile wurde bereits im letzten Kapitel erläutert, die beiden use-Anweisungen werden unter Stil und Struktur erläutert. In den beiden folgenden Zeilen werden die skalaren Variablen $a und $b mit dem Schlüsselwort my deklariert, außerdem werden ihnen die Werte 2 bzw. 3 zugeordnet. Das Schlüsselwort my beschreibt den Geltungsbereich einer Variable. Die dritte Zeile beginnt mit einer in " eingeschlossene Zeichenkette. Die Variablen werden innerhalb der Zeichenkette als String ersetzt. Hinter der Zeichenkette werden $a und $b mit dem mathematischen Operator + verknüpft. Sie werden also als Zahlen interpretiert und das Ergebnis wird ausgegeben. Abgeschlossen wird die Ausgabe durch einen Zeilenumbruch.

Perl stellt uns eine Vielzahl mathematischer Operatoren zur Verfügung, neben der hier verwendeten Addition ist uns u.a. auch Subtraktion, Multiplikation, Division und Potenzieren möglich (siehe Operatoren).

Zeichenketten (Strings)

$var = 'text';
$var = "text";

Skalarvariablen können auch Zeichenketten (Strings) enthalten. Diese werden, von einfachen (') oder doppelten (") Anführungszeichen umschlossen, der Variablen zugewiesen. Der Unterschied zwischen einfachen und doppelten Anführungszeichen besteht in der sogenannten Variableninterpolation. Dazu ein Beispiel:

#!/usr/bin/perl

use strict;
use warnings;

my $var = 5;
my $text = "Variable enthält: $var";
my $text2 = 'Variable enthält: $var';
print $text;
print "\n";
print $text2;
print "\n";

erzeugt folgende Ausgabe:

Variable enthält: 5
Variable enthält: $var

Was ist passiert? Bei der Zuweisung an $text, bei der wir doppelte Anführungszeichen benutzt haben, sucht der Interpreter in der zugewiesenen Zeichenketten nach Vorkommen von $Variablenname, und ersetzt diese durch den Inhalt der jeweiligen Variable – in unserem Fall also durch den Inhalt von $var. Dies nennt man Interpolation. Eine solche Interpolation wird jedoch bei einfachen Anführungszeichen nicht vorgenommen.

Nicht nur Variablennamen, sondern auch Steuercodes wie \n werden bei einfachen Anführungszeichen ignoriert. Beispielsweise erzeugt

 print "\n";

einen Zeilenumbruch, wohingegen

 print '\n';

einfach die Zeichenfolge \n ausgibt.


Beispiel

Nehmen wir also nochmal das Additions-Beispiel von vorhin und verschönern es ein wenig.

#!/usr/bin/perl

use strict;
use warnings;

my $a = 2;
my $b = 3;
my $c = $a + $b;

print "$a + $b = $c\n";

Ausgabe:

2 + 3 = 5

Arrays

Ein Array enthält im Gegensatz zu einem Skalar nicht genau einen, sondern keinen, einen oder mehrere Werte. Dabei können diese Werte völlig frei gemischt werden. Es ist also möglich in dem selben Array Texte, Ganzzahlen, Kommazahlen u.ä. zu speichern. Zur Unterscheidung zwischen Arrays und Skalaren ist dem Array ein At-Zeichen (@) als Sigilie vorangestellt. Man kann sich ein Array als Liste von Skalaren vorstellen. Dabei werden die einzelnen Werte über ganze Zahlen (Integer) eindeutig identifiziert. Hier ein kleines Beispiel:

#!/usr/bin/perl

use strict;
use warnings;

my @halblinge = ( "Bilbo", "Frodo", "Sam" ); # einfache Liste von Halblingen
print $halblinge[0], "\n";                   # gibt Bilbo aus
print $halblinge[1], "\n";                   # gibt Frodo aus

Was geschieht hier? Nun, zuerst wird ein Array mit dem Namen @halblinge erzeugt. Diesem wird eine Liste zugewiesen. Listen werden in Perl in einfachen Klammern eingeschlossen. Da die Werte in der Liste Strings (Text) sein sollen, müssen sie als solche kenntlich gemacht werden. Dies kann man u.a. mit doppelten Anführungszeichen tun. Als letztes müssen die Werte einer Liste dann noch mit Kommata getrennt werden. Bei Listen von Strings ist es mithilfe des Listenoperators qw möglich, auf Kommata und doppelte Anführungszeichen zu verzichten. Die einzelnen Strings werden dann nur durch Leerzeichen getrennt. Mit dem qw-Operator ( quoted words / Wörter in Anführungszeichen ) sieht das obige Beispiel so aus:

#!/usr/bin/perl

use strict;
use warnings;

my @halblinge = qw( Bilbo Frodo Sam );       # einfache Liste von Halblingen
print $halblinge[0], "\n";                   # gibt Bilbo aus
print $halblinge[1], "\n";                   # gibt Frodo aus

Man kann die Werte einer Liste auch mit => trennen, dies werden wir bei den Hashes sehen.

Aber was soll das nun mit der zweiten und dritten Zeile? Da steht ja nun wieder ein Dollar-Zeichen vor dem Variablennamen. Das ist auch richtig so, denn aus dem Array soll nur ein einzelner skalarer Wert ausgegeben werden. Den Variablennamen mit einem vorgestellten @ an print zu übergeben, würde print aber dazu veranlassen alle Werte des Arrays auszugeben.

Perl unterscheidet hier Arrays von Skalaren, indem es an das Ende der Variable schaut. Dort ist nämlich der Platz des Wertes, auf den zugegriffen werden soll, in eckige Klammern geschrieben. Hierbei ist zu beachten, dass Arrays bei Null anfangen zu zählen und nicht bei Eins, wie man evtl. annehmen könnte.

Die Anzahl der Elemente eines Arrays erhält man, wenn man das Array im skalaren Kontext interpretiert:

my $anzahlHalblinge=@halblinge; 
print $anzahlHalblinge;            # ergibt 3

Man könnte bei diesem Beispiel den skalaren Kontext explizit angegeben indem man die interne scalar-Funktion benutzt. Somit könnte das vorhergehende Beispiel auch so aussehen:

print scalar @halblinge;            # ergibt 3 ( Klammern sind optional, timtowtdi! )

Hashes (assoziative Arrays)

Hashes sind ganz ähnlich wie Arrays Listen von Werten. Aber im Unterschied zu Arrays sind Hashes nicht geradlinig durchnummeriert, sondern jeder Wert bekommt seinen eigenen Namen (key) der frei gewählt werden darf, weshalb sie auch assoziative Arrays genannt werden. Dadurch lassen sich viele Programmieraufgaben wesentlich schneller und schöner lösen, als es mit normalen Arrays möglich wäre.

Damit Hashes von Arrays und Skalaren unterschieden werden können, wird dem Hash ein Prozentzeichen (%) als Sigilie vorangestellt. Man beachte, dass auch bei Hashes dieses Prozentzeichen in ein Dollarzeichen gewandelt wird, wenn auf einzelne, skalare Werte des Hashes zugegriffen wird.

Eine weitere Eigenheit von Hashes ist es, dass der Schlüssel in geschweiften Klammern, und nicht wie bei Arrays in eckigen Klammern eingeschlossen wird.

my %telefon = (
    'MaxMuster'   => '0815/12345',
    'KarlMaier'   => '0815/12346',
    'HansMueller' => '0815/12347' 
);
print $telefon{'KarlMaier'}, "\n";  # gibt 0815/12346 aus!

Um in diesem Beispiel auf alle Schlüssel (in diesem Fall die Namen) zugreifen zu können, kann man sich an der keys-Funktion von Perl bedienen. Diese Funktion liefert eine Liste der Schlüssel aus dem Hash zurück.

my @list_keys = keys %telefon;
for (@list_keys) {
    print $_, "\n";
}

oder kompakter:

for (keys %telefon) {   # Variablen sparen
    print $_, "\n";
}

Dieses Beispiel liefert folgende Ausgabe:

MaxMuster
KarlMaier
HansMueller

Natürlich muss es hier auch eine Möglichkeit geben, die Werte der Identifier im Listenkontext auszugeben. Das Gegenstück zur keys-Funktion ist die values-Funktion. Sie funktioniert nach demselben Prinzip.

my @list_values = values %telefon;
for (@list_values) {
    print $_, "\n";
}

oder kompakter:

for (values %telefon) {   # Variablen sparen
    print $_, "\n";
}

liefert:

0815/12345
0815/12346
0815/12347

WARNUNG:

Die Reihenfolge in denen die Wertpaare in einem Hash angeordnet sind, ist nicht immer dieselbe. Nur weil ein Hash bei einem Durchlauf die Keys oder Values in einer bestimmten Reihenfolge ausspuckt, bedeutet das nicht zwangsläufig, dass das beim nächsten Durchlauf auch noch so sein muss. Zur Sicherheit sollte man hier von der sort-Funktion Gebrauch machen.

Beispiel:

for (sort keys %telefon) {   # Sortierte Liste der Schluessel
    print $_, "\n";
}

Hier ist gewährleistet, dass die Liste, sofern der Hash nicht verändert wurde, immer dieselbe bleibt.


Variablenklassifizierung und Fallbeispiele

Klassifizierung von Variablen

Variablen können verschiedenste Aufgaben erfüllen. Eine Variable kann beispielsweise einen oder mehrere Werte enthalten. Perl unterscheidet Variablen anhand von Typkennzeichen, den Sigilien. Variablen die einen Wert enthalten werden Skalare genannt und mit einem $ gekennzeichnet. Variablen mit einer geordneten Liste von Werten werden Arrays genannt und mit einem @ gekennzeichnet.

Eine skalare Variable kann z.B. einen String enthalten. Das Hello World-Beispiel kann also auch so aussehen:

my $ausgabe = "Guten Morgen, Welt!\n";  # Variable setzen
print $ausgabe;                         # Variablen ausgeben

Wenn Sie aufgepasst haben, werden Sie feststellen, dass die Variable $ausgabe nicht deklariert worden ist. Perl erkennt automatisch anhand des $-Zeichens, dass es sich um eine skalare Variable handelt. Die Funktion print gibt dann den Wert der Variablen aus.

Eine Array-Variable beginnt stattdessen mit einem @-Zeichen. (Wenn Sie nun Array und Skalar gar nicht auseinander halten können, versuchen Sie mal folgender Eselsbrücke: $ = $(s)kalar @ = @(a)rray Man kann sich hier sehr einfach das $ als s vorstellen und das @ als a.)

Perl besitzt aber noch mehr Variablentypen, wie z.B. Hash, handle, typeglob, und allen wird zur Unterscheidung ein Typkennzeichen vorangestellt. Hier eine kleine Liste aller Typkennzeichen, denen Sie bei Perl begegnen werden.

Typ Kennzeichen Beispiel Ist ein Name für:
Skalar $ $bsp Ein individueller Wert (Zahl oder String)
Array @ @test Eine Liste von Werten mit einer Ganzahl als Index
Hash % %zinsen Ein Gruppe von Werten mit einem String als Index
Subroutine & &was Ein aufrufbares Stück Perl-Code
Typeglob * *maus Alles namens maus

Aber jetzt nicht zurückschrecken. Die Variablen können ohne weiteres und ohne besondere Syntax einfach umgewandelt werden. Perl-Scripte sind verhältnismäßig einfach zu lesen, weil Hash gegen Array etc. schnell heraussticht.

Singularitäten

So wie Sie vorher gesehen haben, können Sie Skalaren mit dem Operator einen neuen Wert zuweisen. Skalaren kann jede Form von skalaren Werten zugewiesen werden.

  • Undefinierter Wert
  • Integer (ganze Zahlen)
  • Fließkommazahlen
  • Strings (Zeichenfolgen)
  • Referenzen auf Subroutinen
  • etc.

Wie bei der Shell bei Unix, können Sie verschiedene Quoting-Mechanismen verwenden, um Werte zu erzeugen. hier einige Beispiele

my $unbekannt      = undef;                    # undefinierter Wert   
my $sechs_mal_neun = 54;                       # eine ganze Zahl
my $pi             = 3.14159265;               # eine rationale Zahl
my $chem           = 93.5ds2;                  # wissenschaftliche Notation
my $tier           = 'hund';                   # String
my $test           = "ich habe einen $tier";   # String mit Interpolation
my $preis          = 'kosten 255€';            # String ohne Interpolation
my $abc            = $preis;                   # Wert einer anderen Variable
my $bild           = $rahmen * $wand;          # ein Ausdruck
my $exit           = system("vi $file");       # numerischer Status eines Befehls
my $cwd           = `cwd`;                     # Textausgabe eines Befehls

Nicht verzweifeln. Das sieht komplizierter aus, als es wirklich ist. Hiermit wollte ich nur verdeutlichen, dass ein Skalar sehr viel enthalten kann. Aber es kann noch mehr, wie z.B. Referenzen auf andere Datenstrukturen, Subroutinen und Objekte.

my $ary = \@array;                        # Referenz auf ein bekanntes Array
my $hsh = \%hash;                         # Referenz auf einen bekannten Hash
my $sub = \&was;                          # Referenz auf eine bekannte Subroutine
 
my $ary = [1,2,3,4,5];                    # Referenz auf ein nicht benanntes Array
my $hsh = {AP => 20, HP =>2};             # Referenz auf einen nicht benannten Hash
my $sub = sub { print $zeit };            # Referenz auf eine nicht benannte Subroutine
  
my $fido = neuer Hund 'Boss';             # Referenz auf ein Objekt, ''neuer'' ist eine Methode im Namensraum ''Hund''

... ... ...


Spezialvariablen

Das Persönliche Fürwort $_

Eine Eigenheit von Perl ist die Vielzahl von vordefinierten Spezialvariablen. Die perlischte Spezialvariable ist $_.

Im Deutschen gibt es die Personalpronomen er, sie und es. Analog gibt es in Perl die Default-Variable $_. Man kann Werte an $_ zuweisen um bekanntzugeben wovon gerade die Rede ist. Andererseite weisen diverse Sprachkonstrukte automatisch Werte an $_ zu. Die meisten stringverarbeitenden Funktionen benutzen $_ als Standardeingabe.

In einer Schleife über die Werte Himbeereis, Regina und hitzefrei ist klar wovon jeweils die Rede ist, also kann man $_ verwenden.

foreach ('Himbeereis', 'Regina', 'hitzefrei' ) {
    print "Ich mag $_.\n";
}

Gibt aus:

 Ich mag Himbeereis.
 Ich mag Regina.
 Ich mag hitzefrei.

Bei der Stringverarbeitung kann man die implizite Variable $_ verwenden um prägnant zu programmieren.

while (<STDIN>) {                # Zeilenweise einlesen von der Standardeingabe STDIN. 
                                 # Die gelesene Zeile wird automatisch in $_ gespeichert.
    s/BöserText/GuterText/;       # Ein Suchen-Ersetzen-RegEx : Ersetzt 'BöserText' durch 'GuterText' in der Variablen $_;
    s/PHP/Perl/;                 # Ein weiterer Suchen-Ersetzen-Regex. Merke : Perl nimmt $_ wenn keine andere Variable gesetzt ist 
    print;                       # Ausgabe von $_, welches nun nur noch "GutenText" und kein "PHP" mehr enthalten sollte.
}                                # Hole die nächste Zeile

Das gleiche Programm könnte man auch so schreiben :

while ( my $line = <STDIN> ) {
    $line =~ s/BöserText/GuterText/;
    $line =~ s/PHP/Perl/; # :-|
    print $line;
}

Anstatt der impliziten Variable $_ wurde hier explizit die Variable $line benutzt.

Über das Für und Wider dieser Spezialvariable kann man sich sicher streiten, unbestreitbar ist dessen Nutzung in diversen Beispielen im Internet. Mit etwas Erfahrung und dem Wissen um die Eigenschaften dieser Variable kann durch sie die Lesbarkeit des Quellcodes verbessert werden.

Gerade zu Begin der eigenen Perl-Karriere kann die Nutzung von $_ eventuell hinderlich sein. Auch in größeren Projekten kann man sich durch übermäßige Nutzung dieses Features leider ab und an in die eigenen Füße schießen. Trotz aller dieser Widrigkeiten kann man durch $_ kleine Scripte noch kleiner machen und dadurch die "Produktionsgeschwindigkeit" erhöhen.

Auf jeden Fall muss man beim Programmieren beachten, dass $_ global ist. Wenn $_ innerhalb einer Funktion geändert wird ändert sie auch den Wert außerhalb der Funktion. Um sich davor zu schützen kann man die Variable für den Bereich in dem sie geändert wird lokal machen.

sub addition {
    my ($a); 

    { local $_;  
      $a += $_ for @_; # @_ enthält die Funktionsparameter
    }
    $_ = $a unless defined wantarray;

    return $a
}

$val = addition(1,1);  # $val = 2
addition(1,1);       # $_ = 2

Eigene Funktionen ändern $_ nicht automatisch, wenn bei ihrem Aufruf kein lvalue angegeben ist, der den Wert aufnimmt. Perl kennt aber die eingebaute Funktion wantarray die beim Thema Kontext von Funktionen eine Rolle spielt. Ist ihr Rückgabewert undef dann wurde die Funktion im sogenannten void-Kontext aufgerufen und die Programmiererin könnte $_ explizit setzen um das Verhalten der Funktion mehr perlish zu gestalten.


Einfache Ein-/Ausgabe

Ein-/Ausgabe

Nun verfeinern wir das 'Hello World!'-Programm aus den ersten Schritten etwas. Dieses Mal soll das Programm den Benutzer dynamisch ansprechen.

#!/usr/bin/perl
use strict;
use warnings;

# Zur Eingabe auffordern
print "Bitte geben Sie Ihren Namen ein:\n";

# Eine Zeile einlesen
my $name = <STDIN>;

# Zeilenumbruch entfernen
chomp $name;

# Gruß ausgeben
print "Hallo, $name, einen schönen Tag noch!\n";

Die erste Anweisung fordert mit "Bitte geben Sie Ihren Namen ein:" den Nutzer zur Eingabe auf. Die zweite Anweisung liest eine Zeile ein und legt sie in der Variablen $name ab. Dies ist eine skalare Variable, die genau einen Wert aufnehmen kann, dieser eine Wert ist die gesamte eingelesene Zeile. Mit der dritten Anweisung werden abschließende Zeilenumbrüche von der Eingabe entfernt -- wenn die Eingabe von der Tastatur stammt, so ist dies der Zeilenumbruch vom Drücken der Taste Return, mit der man die Eingabe abgeschlossen hat. Die vierte Anweisung gibt einen Gruß aus, nachdem der Wert der Variablen interpoliert wurde.

STDIN ist eine Kurzform für standard input, der Standard-Eingabekanal. Dieser Eingabekanal ist für ein von der Kommandozeile gestartetes Programm die Tastatur.

Nicht zu verwechseln ist <STDIN> mit dem Diamantoperator <>. Der Diamantoperator liest nur dann vom Standard-Eingabekanal ein, wenn beim Start des Programms keine Kommandozeilenargumente angegeben wurden.

Es gibt neben STDIN noch STDOUT, den Standardausgabekanal, und STDERR, den Standardkanal für Fehlermeldungen. Ein- und Ausgaben kommen immer aus einem Kanal beziehungsweise fließen immer dahin.

Der Standard-Eingabekanal muss nicht immer auf die Tastatur zeigen, sondern kann auch umgelenkt werden.

Folgendes Kommandozeilen-Beispiel gibt den Namen Hans aus und leitet die Ausgabe so, dass sie zur Eingabe für obiges Programm, das hier eingabe.pl heißt, wird.

echo Hans | ./eingabe.pl

Folgendes Kommandozeilen-Beispiel gibt den Namen Hans in eine Textdatei aus. Diese Textdatei wird dann zur Eingabe für obiges Programm, das hier eingabe.pl heißt.

echo Hans > name.txt
./eingabe.pl < name.txt

Die beiden Beispiele sind nicht perlspezifisch, sondern abhängig von dem Betriebssystem, und funktionieren auf den gängigen Befehlszeilen vieler UNIX-Varianten.

Das zweite Beispiel zur Eingabeumlenkung liest die Zeile aus einer Datei. Diese Umlenkung kann man auch mit Bordmitteln von Perl erreichen. Hierzu öffnen wir die Datei name.txt selbst und lesen daraus.

#!/usr/bin/perl
use strict;
use warnings;

# Kanal schließen
close (STDIN);

# Datei als Standardeingabe öffnen
open (STDIN, '<', 'name.txt') or die 'Konnte name.txt nicht zum Lesen öffnen';

# Eine Zeile von STDIN einlesen
my $name = <>;

# Zeilenumbruch entfernen
chomp $name;

# Gruß ausgeben
print "Hallo, $name, einen schönen Tag noch!\n";

Die erste Anweisung schließt den (implizit geöffneten) Kanal von der Tastatur, um ihn danach so zu öffnen, dass er aus der Datei name.txt liest. Das zweite Argument, die spitze linke Klammer, bedeutet dabei, dass die Datei zur Eingabe gelesen wird.

  • Lesen Sie mit perldoc -f nach, wie close und open funktionieren.
  • open ist eine sehr mächtige Funktion. Versuchen Sie zunächst nur, ihre Funktionsweise in Ansätzen zu verstehen.
  • Schreiben Sie ein Programm, das Ihren Vor- und Nachnamen von der Tastatur einliest und danach ausgibt.
  • Schreiben Sie Ihr Programm so um, dass es die Eingaben aus einer Datei liest. Hinweis: Der Diamantoperator liest stets eine Zeile ein.
  • Was passiert bei obigem Programm, wenn Sie nichts eingeben oder wenn die Textdatei, aus der Sie einlesen, leer ist? Schlagen Sie die Fehlermeldung auf der Handbuchseite perldiag nach!


Dateien

Dateitest-Operatoren

Ein Dateizugriff ist ein sehr systemnaher Vorgang. Zugriffe auf nichtexistente Dateien können zu Abstürzen unseres Programms führen. Um das zu vermeiden muß unser Perl-Programm sich häufig zur Laufzeit, vor dem eigentlichen Dateizugriff, informieren, was genau auf dem Dateisystem los ist. Dazu muß der Programmierer seinem Programm die richtigen Fragen an die Hand geben.

Perl stellt eine ganze Reihe von Operatoren zur Verfügung um Dateien zu testen. Diese sogenannten Dateitest-Operatoren ( auch -X-Operatoren genannt ) ermöglichen es dem Programmierer, zu überprüfen wie der Zustand einer Datei ist. Hier eine komplette Liste der vorhandenen Operatoren:

-r   Datei / Verzeichnis ist für effektiven Benutzer oder Gruppe lesbar
-w   Datei / Verzeichnis ist für effektiven Benutzer oder Gruppe schreibbar
-x   Datei / Verzeichnis ist für effektiven Benutzer oder Gruppe ausführbar
-o   Datei / Verzeichnis gehört effektivem Benutzer
-R   Datei / Verzeichnis ist für tatsächlichen Benutzer oder Gruppe lesbar
-W   Datei / Verzeichnis ist für tatsächlichen Benutzer oder Gruppe schreibbar
-X   Datei / Verzeichnis ist für tatsächlichen Benutzer oder Gruppe ausführbar
-O   Datei / Verzeichnis gehört tatsächlichem Benutzer
-e   Datei / Verzeichnis existiert
-z   Datei existiert und hat die Größe null ( für Verzeichnisse immer unwahr )
-s   Datei existiert und hat eine andere Größe als null ( Wert ist Größe in Bytes )
-f   Angabe ist eine "einfache" Datei
-d   Angabe ist ein Verzeichnis
-l   Angabe ist ein symbolischer Link
-S   Angabe ist ein Socket
-p   Angabe ist eine benannte Pipe ( fifo )
-b   Angabe ist eine spezielle Blockdatei
-c   Angabe ist eine zeichenorientierte Datei
-u   Datei / Verzeichnis ist setuid
-g   Datei / Verzeichnis ist setgid
-k   Datei / Verzeichnis hat das "Sticky Bit" gesetzt
-t   Dateihandle ist ein TTY
-T   Datei sieht aus wie eine Text-Datei
-B   Datei sieht aus wie eine Binär-Datei
-M   "Alter" der Datei ( in Tagen )
-A   Zeit des letzten ( in Tagen )
-C   Letzte Änderung des Inode ( in Tagen )

Hier ein Beispiel um die Funktion dieser Operatoren zu erläutern:

1 #!/usr/bin/perl
2 use strict;
3 use warnings;
4 # überprüfen ob Datei existiert
5 
6 my $datei = '/tmp/testfile';
7 if ( -e $datei ) {
8     print "Datei existiert\n";
9 }

Dateien öffnen und schließen

Um eine Datei zu öffnen benutzt man in Perl die open-Funktion, zum Schließen die close-Funktion.


 1 #!/usr/bin/perl
 2 use strict;
 3 use warnings;
 4 # Datei überprüfen und öffnen
 5 
 6 my $datei = '/tmp/testfile';
 7 if ( -e $datei ) {
 8     print "Datei $datei existiert\n";
 9     open (my $fh, "<", $datei) or die "Kann Datei $datei nicht oeffnen: $!";
10     close $fh;
11 } 
12 else {
13   print "Datei $datei existiert nicht\n";
14 }

In diesem Beispiel wird zuerst überprüft, ob die Datei existiert. Nachdem dieser Test erfolgreich ist, wird die entsprechende Meldung ausgegeben und direkt im Anschluss die Datei geöffnet (standardmäßig im Read-Modus). Würde das fehlschlagen, würde das Programm mit entsprechender Fehlermeldung versterben (die). Zuletzt wird das File wieder geschlossen.

Modi für Dateihandles

Im obigen Beispiel wurde eine Datei standardmäßig im Lesemodus geöffnet. Was ist jedoch, wenn wir eine Datei schreibend öffnen wollen ( zB um ein Logfile zu schreiben )? Für diese Aufgabe gibt es die sogenannten Modi mit denen eine Datei geöffnet werden kann. Aus historischen Gründen kann die Funktion open mit zwei oder mit drei Argumenten benutzt werden. Beim Aufruf mit zwei Argumenten wird der Modus dem Dateinamen vorangestellt. Allgemein empfohlen ist jedoch die modernere Art des Aufrufes mit drei Argumenten.

Hier die Übersicht über die Modi:

<   Pfad     Zugriff nur lesend
>   Pfad     Zugriff nur schreibend ( neu anlegen / bestehende Datei überschreiben )
>>  Pfad     Zugriff nur schreibend ( neu anlegen / an bestehende Datei anhängen )
+<  Pfad     Lese-/Schreibzugriff
+>  Pfad     Lese-/Schreibzugriff ( neu anlegen / bestehende Datei überschreiben )
+>> Pfad     Lese-/Schreibzugriff ( neu anlegen / an bestehende Datei anhängen )
| Befehl     Schreibhandle an Befehl
Befehl |     Lesehandle von Befehl

Somit könnte man das obige Beispiel auch wie folgt schreiben:

 1 #!/usr/bin/perl
 2 use strict;
 3 use warnings;
 4 # Datei überprüfen und öffnen
 5 
 6 my $datei = '/tmp/testfile';
 7 if ( -e $datei ) {
 8     print "Datei $datei existiert\n";
 9     open (my $fh, '<', $datei) or die "Kann Datei $datei nicht zum Lesen oeffnen: $!";
10     close $fh;
11 }

Dateien schreiben

Jetzt, wo wir wissen, wie man eine Datei entweder lesend oder schreibend öffnet, wollen wir natürlich auch etwas mit diesen Dateien anstellen. Im nächsten Beispiel schreiben wir eine Zeile in eine neue Datei:

 1 #!/usr/bin/perl
 2 use strict;
 3 use warnings;
 4 # in Datei schreiben
 5 
 6 my $datei = '/tmp/testfile';
 7 if ( -e $datei ) {                                                   # Wenn Datei existiert, tun wir garnichts
 8     print "Datei $datei existiert\n";
 9 }
10 else {                                                               # Wenn Datei nicht existiert, öffnen, bzw. anlegen.
11     open (my $fh, '>', $datei) or die "Kann Datei $datei nicht zum Schreiben oeffnen: $!\n";
12     print $fh "Eine tolle Zeile voller toller Zeichen!\n";           # hier schreiben wir rein
13     close $fh;
14 }

Wie man sieht, ist das Schreiben in eine Datei kinderleicht. Man kann der print-Funktion das Dateihandle übergeben und es einfach hineinschreiben lassen. Achtung: Kein Beistrich!

Dateien auslesen

Einfach nur eine Datei zu schreiben scheint aber auch langweilig. Also wollen wir im nächsten Schritt eine Zeile aus einer Datei einlesen.

 1 #!/usr/bin/perl
 2 use strict;
 3 use warnings;
 4 # eine Zeile auslesen
 5 
 6 my $datei = '/tmp/testfile';
 7 if ( -e $datei ) {
 8     print "Datei $datei existiert\n";
 9     
10     open (my $fh, '<',  $datei) or die "Fehler beim Oeffnen zum Lesen: $!";
11     my $line = <$fh>;
12     print $line;
13     close $fh;
14 }

Dieses Beispiel gibt die erste Zeile von /tmp/testfile zurück. Nun ist das zwar nett, aber eventuell unzureichend für unseren Geschmack, also lesen wir im nächsten Beispiel die komplette Datei aus.

 1 #!/usr/bin/perl
 2 use strict;
 3 use warnings;
 4 # Datei auslesen
 5 
 6 my $datei = '/tmp/testfile';
 7 if ( -e $datei ) {
 8     print "Datei $datei existiert\n";
 9     
10     open (my $fh, '<', $datei) or die "Fehler beim Oeffnen: $!";
11     while (<$fh>) {
12         print $_;
13     }
14     close $fh;
15 }

Das gibt die gesamte Datei aus.

Operatoren

Vorbemerkung

Perl verwendet Operatoren, welche denen von C oder ähnlichen Sprachen stark gleichen. Der '='-Operator wurde ja bereits erwähnt. Er nimmt in Perl eine Sonderstellung ein, da es der einzige Operator ist, der für selbst definierte Objekte nicht umdefiniert werden kann.

Ein wichtiger Aspekt im Zusammenhang mit Operatoren ist ihre Assoziativität. Das heißt ob der Operator sich auf ein Sprachelement links oder rechts von ihm bezieht.

Außerdem ist es wichtig zu wissen, dass für die Operatoren eine bestimmte Reihenfolge festgelegt ist, die darüber entscheidet, wie ein aus mehren Operatoren zusammengesetzter Ausdruck ausgewertet wird.

Das Umdefinieren eines Operators, das später beschrieben wird, kann nur seine Funktionsweise ändern; die Assoziativität und Auswertungsreihenfolge sind nicht änderbar.

Zuweisende und verknüpfende Operatoren

Mathematische Operatoren

Zuerst die Operatoren die wahrscheinlich am meisten gebraucht werden, die mathematischen.

Grundrechenarten

Am häufigsten werden wohl die meisten Programmierer die 4 Grundrechenarten gebrauchen.

$a = 4 + 2;   # Addiere 4 und 2.
$b = 4 - 9;   # Subtrahiere 9 von 4.
$c = 5 * 11;  # Multipliziere 11 mit 5.
$d = 12 / 4;  # Dividiere 12 durch 4. $d enthält nun also 3.

Es fehlt uns also an nichts, alle anderen mathematischen Funktionen könnten wir nun herleiten, aber Perl bietet noch mehr.

Für jede Grundrechenart gibt es nach dem Vorbild von C/C++ auch einen Zuweisungsoperator:

#!/usr/bin/perl

use strict;
use warnings;

my $a = 1;    # Deklaration und Initialisierung
$a += 9;      # Addiere 9 zu $a.
$a -= 6;      # Ziehe 6 von $a ab
$a *= 3;      # Multipliziere $a mit 3
$a /= 2;      # Teile $a durch 2
print "$a\n";
Andere Rechenarten

Perl stellt auch höhere mathematische Operatoren zur Verfügung.

# Potenzieren
my $a = 2 ** 10;      # 2 Hoch 10, sprich 2*2*2*2*2*2*2*2*2*2 = 1024.

# Ermittlung von Ganzzahldivisions-Resten
my $b = 13 % 7;       # 13 Modulo 7 = 6.

# Quadratwurzel
my $c = 49 ** 0.5;    # 7 * 7 = 49
my $d = sqrt(36);     # 6 * 6 = 36

# dritte Wurzel
my $e = 27 ** (1/3);  # 3 * 3 * 3 = 27

Der Operator '**' dient zum Potenzieren; er sollte nicht mit dem bitweisen Operator '^' verwechselt werden, der in einigen Programmiersprachen zum Potenzieren dient.

Wurzelziehen muß im allgemeinen als Potenzieren mit dem Kehrwert des Wurzelexponenten betrachtet werden. Für die Quadratwurzel steht aber zusätzlich die Funktion sqrt($parameter) zur Verfügung.

Für die Ganzzahldivision steht weder ein Operator, noch eine Funktion zur Verfügung, aber mit Hilfe des Modulo-Operators % (s.o.) läßt sich eine entsprechende eigene Funktion leicht erstellen.

#!/usr/bin/perl

use strict;
use warnings;

print div(13, 7) ."\n";

sub div {
  return ($_[0] - $_[0] % $_[1]) / $_[1] ;
}

Zuerst wird mit dem Modulo Operator der Rest der Division der beiden Argumente ermittelt.

Hinweis: Da das Erstellen von eigenen Funktionen noch nicht erläutert wurde, hier kurz und knapp einige Hinweise:

  • sub ist das Schlüsselwort zur Erstellung einer eigenen Funktion.
  • return erzeugt den Ausgabewert einer Funktion.
  • $_[0] und $_[1] sind die Handler für den 1. und den 2. Funktionsparameter. Perl fängt aber bei 0 an zu zählen.


Eine allgemeine Funktion für den Logarithmus zu einer beliebigen Basis steht nicht zur Verfügung. Aber die Funktion log kann den natürlichen Logarithmus berechnen. Die Mathematiker unter den Lesern wissen natürlich, daß dessen Basis die Eulersche Zahl e ist, außerdem, daß man damit auf einfache Weise eine Funktion zur Ermittlung der Logarithmen anderer Basen erstellen kann.

#!/usr/bin/perl

use warnings;
use strict;

print logarithmus(1000, 10) . "\n";

sub logarithmus {
  return log($_[0])/log($_[1]);
}
Inkrementieren und Dekrementieren

Zum simplen Erhöhen oder Verringern einer Variable scheint eine normale Zuweisung oft zu lang oder (in Sonderfällen) zu unübersichtlich.

$a = $a + 1;
$b = $b - 1;

Zur Verkürzung gibt es, ähnlich in C, die Operatoren ++ und -- um diese Statements zu verkürzen.

$a++;         # Rückgabe von $a, dann Inkrementieren von $a.
++$a;         # Inkrementieren von $a, dann Rückgabe von $a.
 
$b--;         # Rückgabe von $b, dann Dekrementieren von $b.
--$b;         # Dekrementieren von $b, dann Rückgabe von $b.

Zu beachten ist hier unbedingt die Position des '++'- bzw. '--'–Operators. So hat zum Beispiel das folgendes Statement nicht die Wirkung auf $b die der Ungeübte auf den ersten Blick vermutet.

$a = 9;
$b = $a++;

In diesem Beispiel besitzt die Variable $b am Ende den Wert 9, da $a zuerst zurückgegeben und dann erhöht wurde. Die gewünschte Wirkung lässt sich mit dieser Konstruktion erreichen.

$a = 9;
$b = ++$a;

Nun wird $a zuerst erhöht und dann an $b zurückgegeben. Nun hat $b den Wert 10.

Stringverknüpfungs–Operatoren

Des Weiteren gibt es spezielle Operatoren um Strings zusammenzufügen, welche von der Programmiersprache PHP übernommen wurden. Durch die Typenlosigkeit Perls ist es notwendig mitzuteilen, ob man zwei Variablen, die möglicherweise Ziffern beinhalten, wie Zahlen oder wie Zeichenketten behandeln soll.

$b = 'Wiki';
$c = 'books';
$d = 42;
$a = $b . $c . $d;   # Verkette $b, $c und $d.
print $a;            # Gibt "Wikibooks42" aus.
print "$b$c$d";      # gibt ebenfalls "Wikibooks42" aus

Der Wiederholungsoperator ( "x" ) vervielfältigt den linken String um den angegebenen rechten Wert.

$b = 'o';
$b = $b x 10;               # Füge $b zehnmal zusammen.
print 'Wikib' . $b . 'ks';  # Gibt "Wikibooooooooooks" aus.

Bitweise Operatoren

Als nächstes die Operatoren, mit denen wir Zahlen bitweise vergleichen können.

Bitweises AND

Der Operator "&" für das bitweise AND vergleicht jeweils 2 Bits miteinander; nur wenn beide 1 sind, ist das Ergebnis auch 1. Am besten demonstrieren wir das ganze einmal an einem Beispielprogramm:

#!/usr/bin/perl
# bitweisesAND.pl
# Demonstration bitweises AND.
  
my ($foo, $bar, $baz);
 
$foo = 1; # In Bits: 0000 0001
$bar = 3; # In Bits: 0000 0011
 
$baz = $foo & $bar; 
# Der bitweise And-Operator.
# Wir vergleichen jedes Bit:
# 0000 0001
# 0000 0011
#----------
# 0000 0001
 
print '$foo: '.$foo."\n";
print '$bar: '.$bar."\n";
print '$baz: '.$baz."\n";

Und die Ausgabe:

$foo: 1
$bar: 3
$baz: 1
Bitweises OR

Der OR–Operator '|' dient wie auch & dem bitweisem Vergleich zweier Zahlen. Wie der Name schon vermuten lässt wird das Ergebnisbit nur auf 1 gesetzt wenn wenigstens eines der beiden Bits 1 ist.

Hier das Beispielprogramm:

#!/usr/bin/perl -w
# bitweisesOR.pl
# Demonstration bitweises OR.
 
my ( $foo, $bar, $baz );
 
$foo = 5;  # In Bits: 0000 0101
$bar = 15; # In Bits: 0000 1111
 
$baz = $foo | $bar; 
# Der bitweise Or-Operator.
# Wir vergleichen jedes Bit:
# 0000 0101
# 0000 1111
#----------
# 0000 1111
 
print '$foo: '.$foo."\n";
print '$bar: '.$bar."\n";
print '$baz: '.$baz."\n";

Und hier wiedermal die Ausgabe:

$foo: 5
$bar: 15
$baz: 15
Bitweises XOR

Der XOR–Operator ^ dient wie seine Geschwister dem bitweisem Vergleichen von Zahlen; er verhält sich ähnlich dem OR–Operator, jedoch wird beim Ergebnis ein Bit nur auf 1 gesetzt, wenn genau eines der beiden Bits 1 ist. Das nennt man exklusives Oder.

Und hier wieder mal das Beispielprogramm:

#!/usr/bin/perl -w
# bitweisesXOR.pl
# Demonstration bitweises XOR.
 
my ( $foo, $bar, $baz );
 
$foo = 3;  # In Bits: 0000 0011
$bar = 61; # In Bits: 0011 1101
 
$baz = $foo ^ $bar; 
# Der bitweise XOR-Operator.
# Wir vergleichen jedes Bit:
# 0000 0011
# 0011 1101
#----------
# 0011 1110
 
print '$foo: '.$foo."\n";
print '$bar: '.$bar."\n";
print '$baz: '.$baz."\n";

Und die Ausgabe des XOR-Programmes:

$foo: 3
$bar: 61
$baz: 62
praktische Anwendung

Nun wollen wir das ganze doch einmal an einem praktischen Anwendungsbeispiel demonstrieren. Wir tauschen zwei Variablen aus:

#!/usr/bin/perl -w
# PraktischeOperatoren.pl
# Praktische Anwendung eines bitweisen XOR.
 
my ( $foo, $bar );
 
$foo = 3; # Bitweise: 0000 0011
$bar = 4; # Bitweise: 0000 0100
 
$foo = $foo ^ $bar;
     # $foo: 0000 0111
 
$bar = $foo ^ $bar;
     # $bar: 0000 0011
 
$foo = $foo ^ $bar;
     # $foo: 0000 0100
 
print '$foo: '.$foo."\n";
print '$bar: '.$bar."\n";

Und nun die Ausgabe:

$foo: 4
$bar: 3

Wie man sieht, haben wir die beiden Variablen ohne den Einsatz einer Hilfsvariable ausgetauscht. Diese Technik ist sehr elegant, birgt aber auch Risiken, so zum Beispiel bei negativen Zahlen, bzw Zahlen nahe am Ganzzahlvariablenmaximum.

Logische Operatoren

Logische Operatoren dienen dazu, Aussagen miteinander zu vergleichen. Soll zum Beispiel überprüft werden, ob eine Zahl $a im Bereich von 2 bis 5 liegt, so muss man zwei Vergleiche durchführen: ist $a größer oder gleich 2, und ist es kleiner oder gleich 5?

Binäre Operatoren

Das oben genannte Beispiel schreibt sich in Perl so:

 if (2 <= $a and $a <= 5) { ... }

der and-Operator (den man auch als '&&' schreiben kann), liefert nur dann ein wahres Ergebnis zurück, wenn beide verknüpfte Ausdrücke wahr sind.

Analog dazu gibt es den or–Operator (der auch als '||' geschrieben werden kann), der ein wahres Ergebnis zurückgibt, wenn mindestens einer Operanden, also der Ausdrücke links und rechts des Operators, wahr ist.

Beispiel:

 if ($a >= 2 or $a <= -2) { ... }

wird dann wahr, wenn $a größer gleich 2 ist oder kleiner gleich -2.

Obwohl man die Operatoren and und or in den meisten Fällen mit && und || ersetzen kann, muss man beachten, dass and und or einen wesentlich niedrigeren Vorrang haben. Dazu ein Beispiel:

$a = 0;
$b = 2;
$c = 0;
$abc = $a || $b || $c;  # $abc bekommt den Wert 2 zugewiesen.

ersetzt man in diesem Beispiel die || durch ein or passiert jedoch folgendes:

$a = 0;
$b = 2;
$c = 0;
$abc = $a or $b or $c;  # $abc wird 0 zugewiesen, weil der Zuweisungsoperator höheren Vorrang hat.
                        # Ist die Zuweisung fehlgeschlagen, wird die or-Operation durchgeführt.

Der Ternäre Operator

Oft muss man zwischen zwei Alternativen unterscheiden. Dabei kann der ternäre Operator helfen.

#!/usr/bin/perl
use strict;
use warnings;

my $tor_status = 1;
print 'Das Tor ist ', $tor_status ? 'offen' : 'geschlossen', ".\n";

Stringvergleichende Operatoren

Aufgrund der Typenlosigkeit von Perl ist es nicht möglich bei einem Vergleich genau zu sagen was verglichen werden soll. Ein Beispiel: In $a enthält die Zeichenkette '1abc' und $b enthält den Integer 5. Bei dem Vergleich

  if ( $a == $b )

Würde $a (die Zeichenkette) zum Vergleich nach Integer gecastet (konvertiert) werden. Das hat keine direkten Auswirkungen auf $a, aber während des Vergleiches wird $a von 1abc zu 1. Das kann zu unerwünschten Nebenwirkungen führen. Um dieses Problem zu beheben gibt es einige Operatoren zum Vergleich von Zeichenketten. Diese sind:

  • eq ( equal / gleich)
  • ne ( not equal / ungleich )
  • cmp ( compare / vergleiche )
  • lt ( lower than / kleiner als )
  • le ( lower than or equal / kleiner oder gleich )
  • ge ( greater than or equal / größer oder gleich )
  • gt ( greater than / größer als )

Diese Operatoren sollen hier kurz erläutert werden.

  • Der eq–Vergleich zweier Zeichenketten ergibt wahr wenn die beiden Zeichenketten exakt gleich sind.
  • Der ne–Vergleich zweier Zeichenketten ergibt wahr wenn die beiden Zeichenketten nicht gleich sind.

Diese beiden Operatoren sind vergleichbar mit == und !=.

Beispiele:

  'asdf' eq 'asd'      # ergibt falsch
  'asdf' eq 'asdf'     # ergibt wahr
  'asdf' lt 'asdg'     # ergibt wahr
  'asdf' gt 'asdg'     # ergibt falsch

Spezielle Operatoren

Kombinierte Operatoren

Perl erkennt die von C geläufigen Zuweisungsoperatoren und besitzt noch einige mehr. Folgende Zuweisungsoperatoren gibt es:

=    *=   &&=  |=   .=   x=
**=  &=   -=   >>=  %=
+=   <<=  /=   ||=  ^=

Beispiele:

$a += 2;    # $a wird um 2 vergrössert.
$a -= $b;   # $a wird um $b verkleinert
$a .= $b;   # $a und $b werden in $a zusammengefügt(verkettet).
$a &= $b;   # siehe bitweise Operatoren
$a |= $b;   #
$a ^= 2;    #

Der Bereichsoperator

Der Bereichsoperator erstellt eine Liste mit Werten im Bereich zwischen dem linken Operanden und dem rechten Operanden. Wobei sowohl .. als auch ... verwendet werden können (diese sind gleichwertig). Er verhält sich ziemlich intelligent und ist durchaus in der Lage Listen, welche aus Buchstaben bestehen, zu erstellen. Die Listen können zum Beispiel in Schleifen durchlaufen werden, aber auch mit simplen Befehlen.

#!/usr/bin/perl
use strict;
use warnings;
print (10 .. 21);
print "\n"; # Zeilenumbruch ausgeben.
 
# Das ganze geht genausogut mit Schleifen.
for ( 'A' .. 'F' ) { print }

Programmausgabe:

101112131415161718192021
ABCDEF

Der defined-or Operator

Neu in Perl 5.10 ist der defined-or operator // bzw. //=. Er überprüft nicht den Wahrheitsgehalt seines Argumentes, sondern die Definiertheit.


Kontrollstrukturen

Fallunterscheidungen / Verzweigungen

Oft werden Programmteile erst ausgeführt, wenn eine bestimmte Bedingung eingetreten ist. Diese Bedingung muss dann zunächst geprüft werden. Mit den Mitteln, die wir bisher kennengelernt haben, kommen wir nicht zum Ziel. In Perl schaffen hier if-Konstrukte Abhilfe: Die einfachste Fallunterscheidung prüft, ob eine Bedingung zutrifft. Dafür wird vor einen Block die if-Anweisung gesetzt, der die Bedingung in Klammern folgt:

#!/usr/bin/perl
use strict;
use warnings;

# Zur Eingabe auffordern
print "Bitte geben Sie ein Zahl ein:\n";

# Zeile einlesen
my $z = <STDIN>;

# Zeilenumbruch entfernen
chomp $z;

# Ist z 0?
if ( $z == 0 ) {
    # ja, z ist 0
    print "Die Eingabe ist 0\n";
}

Obiges Programm gibt nur dann etwas aus, wenn tatsächlich 0 eingegeben wird.

Die Bedingung, die hinter der if-Anweisung in Klammern steht, wird im boolschen Kontext ausgewertet, der eine Sonderform des skalaren Kontexts ist. Mehr dazu steht im Abschnitt über Kontexte.

Wir möchten nun ein Programm schreiben, das überprüft, ob eine ganze Zahl gerade oder ungerade ist und uns dann eine entsprechende Ausgabe liefert.

#!/usr/bin/perl
use strict;
use warnings;

# Zur Eingabe auffordern
print "Bitte geben Sie eine Zahl ein:\n";

# Zeile einlesen
my $z = <STDIN>;

# Zeilenumbruch entfernen
chomp $z;

# Ist z gerade?
if ( $z % 2 == 0 ) {
    printf ( "%d ist gerade\n" , $z );
}

# Ist z ungerade?
if ( $z % 2 == 1 ) {
    printf ( "%d ist ungerade\n" , $z );
}

Die erste printf-Anweisung wird nur dann ausgeführt, wenn die Bedingung in den runden Klammern nach dem Schlüsselwort if erfüllt ist. Nur wenn sich $z ohne Rest durch 2 dividieren lässt, wird ausgegeben, dass die Zahl gerade ist. Genauso funktioniert auch die zweite if-Bedingung. Mithilfe von else, einem weiteren Schlüsselwort, könnten wir das Programm auch so realisieren:

#!/usr/bin/perl
use strict;
use warnings;

# Zur Eingabe auffordern
print "Bitte geben Sie ein Zahl ein:\n";

# Zeile einlesen
my $z = <STDIN>;

# Zeilenumbruch entfernen
chomp $z;

if ( $z % 2 == 0 ) {
    printf ( "%d ist gerade\n" , $z );
} else {
    printf ( "%d ist ungerade\n" , $z );
}

Die printf-Anweisung, die in den geschweiften Klammern hinter else steht, wird ausgeführt, wenn die Bedingung in der vorherigen if-Anweisung nicht erfüllt ist. Dies entspricht auch der Bedeutung der beiden Wörter if und else in der englischen Sprache: falls (engl. if) die erste Bedingung wahr ist, wird die erste Anweisung ausgeführt, ansonsten (engl. else) wird die zweite Anweisung ausgeführt. Da eine ganze Zahl, die nicht gerade ist, zwangsweise ungerade sein muss, arbeitet das Programm nach wie vor korrekt.

  • Das erste Programm prüft, ob die Eingabe 0 ist. Auf wieviele verschiedene Arte können Sie 0 eingeben?
  • Geben Sie beim ersten Programm 0 but true ein. Wie erklären Sie sich die Ausgabe?
  • Was passiert, wenn Sie keine Zahl eingeben? Schlagen Sie die Fehlermeldungen auf der Handbuchseite perldiag nach!
  • Die Eingabe an ihr Programm kann interaktiv erfolgen oder von einem anderen Programm stammen. Formulieren Sie auf der Kommandozeile eine Befehlsfolge, die die Ausgabe eines Programms ihrem Programm als Eingabe zur Verfügung stellt.
  • Was passiert, wenn Sie oder das andere Programm keine Daten eingeben? Schlagen Sie die Fehlermeldungen auf der Handbuchseite perldiag nach!
  • Geben Sie beim zweiten Programm nicht ganze Zahlen ein. Wie erklären Sie sich die Ausgabe?
  • Schreiben Sie ein Programm, das überprüft, ob die Eingabe positiv, negativ oder 0 ist.

In Perl können wir if-else-Konstrukte beliebig schachteln. Folgendes Beispiel enthält eine if-Abfrage, die sich in einem Anweisungsblock einer anderen if-Abfrage befindet:

#!/usr/bin/perl
use strict;
use warnings;

# Zur Eingabe auffordern
print "Bitte geben Sie das Passwort ein:\n";

# Passwort einlesen
my $passwort = <STDIN>;
chomp $passwort;

# Abfragen, ob das Passwort korrekt ist
if ( $passwort eq "topsecret" ) {
    
    # Passwort korrekt
    print "Wollen Sie ihren Kontostand abfragen?\n";
    my $eingabe = <STDIN>;
    chomp $eingabe;
    
    # Gegebenenfalls Kontostand anzeigen
    if ( $eingabe eq "ja" ) {
        print "Kontostand: 0 Euro\n";
    }
} else {

    # Passwort falsch
    print "Das Passwort war leider nicht korrekt.\n";
}
print "Auf Wiedersehen!\n";


Erst wenn das Passwort korrekt ist, können wir überprüfen, ob der Kontostand angezeigt werden soll. Aus diesem Grund schachteln wir die Fallunterscheidungen. Es empfiehlt sich, auf solche Schachtelungen wenn möglich zu verzichten, um den Quelltext übersichtlich zu gestalten. Hierzu folgendes Beispiel:

#!/usr/bin/perl
use strict;
use warnings;

my $eingabe = 50;

if($eingabe > 42){
    if($eingabe % 2 == 0){
       if($eingabe != 92){
          $eingabe = 0;
       }
    }
}

Mithilfe der logischen Operatoren, die wir schon kennengelernt haben, lässt sich das Programm übersichtlicher schreiben:

#!/usr/bin/perl
use strict;
use warnings;

my $eingabe = 50;

if($eingabe > 42 && $eingabe % 2 == 0 && $eingabe != 92){
    $eingabe = 0;
}

Standardfallunterscheidung

Ein allgemeines Wörtchen zu Wahrheit und Falschheit in Perl: Die Ausdrücke 0, undef und alle Ausdrücke/Bedingungen, die dazu evaluiert werden, sind falsch. Alle anderen Ausdrücke/Bedingungen sind wahr.

 if(BEDINGUNG1)
 {
   ANWEISUNGSBLOCK
 }
 elsif(BEDINGUNG2)
 {
   ANWEISUNGSBLOCK
 }
 elsif(BEDINGUNG3)
 {
   ANWEISUNGSBLOCK
 }
 else
 {
   ANWEISUNGSBLOCK
 }

Die geschweiften Klammern sind zwingend notwendig! Die einfache Fallunterscheidung ist ein Spezialfall der mehrfachen Fallunterscheidung.

negierte Fallunterscheidung

 unless(BEDINGUNG)
 {
   ANWEISUNGSBLOCK
 }
 else
 {
   ANWEISUNGSBLOCK
 }

Dies entspricht einer Verwendung von "if(not BEDINGUNG)".

abgekürzte einfache Fallunterscheidung

Aus manchen Programmiersprachen ist ein abgekürztes Verfahren für einfache Fallunterscheidungen mit jeweils genau einer Anweisung je Fall bekannt. Auch Perl bietet vereinfachte Verfahren hierfür an:

Verfahren 1:

 BEDINGUNG && ANWEISUNG_WAHR;
 BEDINGUNG || ANWEISUNG_FALSCH;

Verfahren 2:

 ANWEISUNG_WAHR if BEDINGUNG;
 ANWEISUNG_FALSCH unless BEDINGUNG;

Schleifen

Schleife mit Laufbedingung

 while(BEDINGUNG)
 {
   ANWEISUNGSBLOCK
 }

Daneben existiert folgende Form der while-Schleife. Sie bewirkt, dass der Anweisungsblock mindestens einmal ausgeführt wird, da die Abfrage der Bedingung erst am Ende stattfinden:

 do
 {
   ANWEISUNGSBLOCK
 }
 while(BEDINGUNG);

Es gibt außerdem eine Kurzform:

 ANWEISUNG while BEDINGUNG;

Schleife mit Abbruchbedingung

 until(BEDINGUNG)
 {
   ANWEISUNGSBLOCK
 }

und analog die Kurzform:

 ANWEISUNG until BEDINGUNG;

Schleife mit Laufvariable

 for(STARTANWEISUNG; LAUFBEDINGUNG; LAUFANWEISUNG)
 {
   ANWEISUNGSBLOCK
 }

In der Regel wird in der Startanweisung die Laufvariable initialisiert, die Laufbedingung enthält einen Grenzwert und vergleicht diesen mit der Laufvariablen und in der Laufanweisung wird die Laufvariable inkrementiert (i.e. um 1 erhöht).

Listenabarbeitungsschleife

 foreach VARIABLE ( LISTENVARIABLE )
 {
   ANWEISUNGSBLOCK
 }

Bei dieser Schleife kann auf das aktuelle Element des abgearbeiteten Arrays mit $_ zugegriffen werden.

Beispiel:

my @liste = qw( asdf jklö 1 2 3 4.56 );
foreach ( @liste ) {
   print "$_" . "\n";
}

Dieses Beispiel würde folgenden Output liefern:

asdf
jklö
1
2
3
4.56

Natürlich kann man in gewohnter TIMTOWTDI-Manier auch hier die alternative Schreibform benutzen falls gewünscht:

#!/usr/bin/perl
print for ( 1 .. 9 );

Dieses Stück Code würde, wie erwartet, die Zahlen von 1 bis 9 ausgeben.

Sprunganweisungen

redo

redo wird benutzt um wieder zum Anfang einer Schleife zu springen, ohne dabei die Laufanweisung auszuführen.

#!/usr/bin/perl
use strict;
use warnings;

print 'hallo'."\n";
for (my $i = 1; $i <= 10; $i++) {
    print 'nun sind wir vor redo'."\n";
    if ($i == 2) {
        print 'wir lassen eine Stelle aus und gehen direkt wieder zum Anfang der Schleife'."\n";
        redo;
    }
    print 'nun sind wir nach redo'."\n";
}

Das gibt folgendes aus:

hallo
nun sind wir vor redo
nun sind wir nach redo
nun sind wir vor redo
wir lassen eine Stelle aus und gehen direkt wieder zum Anfang der Schleife
nun sind wir vor redo
wir lassen eine Stelle aus und gehen direkt wieder zum Anfang der Schleife
nun sind wir vor redo
wir lassen eine Stelle aus und gehen direkt wieder zum Anfang der Schleife
nun sind wir vor redo
...

continue

last

Die last-Funktion wird benutzt um eine Schleife anzuhalten und dann im Programmcode fortzufahren.

#!/usr/bin/perl
use strict;
use warnings;
   
print "hallo\n";
for (my $i = 1; $i <= 100; $i++) {
    print '$i: ' . $i . "\n";
    if ($i == 3) {
        last;
    }
}
print 'last wurde ausgefuehrt, die Schleife wurde angehalten und es geht weiter...';

Das wird folgendes ausgeben:

hallo
$i: 1
$i: 2
$i: 3
last wurde ausgefuehrt, die Schleife wurde angehalten und es geht weiter...

next

Dieses Kommando arbeitet ähnlich wie das bereits beschriebene redo. Es erfolgt ein Sprung zum Beginn der Schleife. Im Gegensatz zu redo, wird jedoch in for, while und until Schleifen die Bedingung mit überprüft. Der Schleifenkopf wird also ausgewertet, als ob die Schleife normal wiederholt würde.

Programmabbrüche

exit

Die exit-Funktion beendet sofort die Programmausführung mit einem angegebenen Exit-Status. Diese Funktion wird verwendet, um das Programm bei Fehlern zu beenden und um mithilfe des zurückgegeben Wertes verschiedene Arten von Fehlern zu unterscheiden.

Beispiel:

if(!-e "nix.txt") { # alternativ: unless ( -e "nix.txt" )
    print "Datei nicht gefunden!";
    exit(1);
}

Hier wird überprüft, ob eine Datei namens nix.txt existiert. Wenn nicht, wird eine Fehlermeldung ausgegeben und und das Programm mit dem Wert 1 beendet.

warn

Die warn-Funktion gibt einen Text sowie die Zeilennummer der betreffenden Zeile im Quelltext auf die Standardfehlerausgabe (STDERR) aus. Diese Funktion wird oft in Kombination mit der exit-Funktion bei der Fehlersuche benutzt, um Fehlermeldungen in eine log-Datei zu schreiben und das Programm zu beenden.

Beispiel:

if(!-e "nix.txt"){
    warn "Datei nicht gefunden!";
    exit(1);
}

Hier wird zuerst überprüft, ob eine Datei "nix.txt" existiert. Wenn nicht, wird eine Fehlermeldung ausgegeben und das Programm beendet. Die Ausgabe würde so aussehen:

Datei nicht gefunden! at beispiel.pl line 2.


Die unten beschriebene Funktion die ist eine vereinfachte Kombination der Befehle warn und exit.

die

Die die-Funktion gibt die Fehlermeldung, die ihr übergeben wird auf der Standardfehlerausgabe ( STDERR ) aus und beendet das Programm mit einem Exit-Status ungleich 0. Dies kann praktisch sein, um schwere Fehler im Vorhinein abzufangen ( zB wenn eine notwendige Datei nicht geöffnet werden kann ).

Beispiel:

open LOGDATEI, '>', '/tmp/log_mein_prog' or die "Kann Log-Datei nicht oeffnen: $!\n";

In diesem Beispiel wird versucht, die Logdatei "/tmp/log_mein_prog" zum Schreiben ( > ) zu oeffnen. Falls dies fehlschlägt, wird das Programm mit die und der mitgegebenen Meldung beendet. Die Spezialvariable $! enthält die System-Fehlermeldung in lesbarem Format ( zB. permission denied ).


Subroutinen

Vorbemerkung

Funktionen bzw. Prozeduren werden in Perl Subroutinen genannt. Subroutinen werden immer dann verwendet, wenn sich ein Vorgang mehrfach verwenden lässt. Teilstücke des Programms werden aus dem Hauptprogramm ausgelagert und durch den Aufruf einer Subroutine eingebunden. Dadurch muss der Vorgang nur einmal programmiert werden. Auch Änderungen des Programms werden erleichtert, weil diese ebenfalls nur an einer Stelle vorgenommen werden müssen. Ein ausgiebiger Gebrauch von Subroutinen ist also empfehlenswert.

Für Experten: Bei einigen älteren Programmiersprachen wird zwischen Prozeduren und Funktionen unterschieden. Funktionen erzeugen Rückgabewerte, Prozeduren nicht. Diese Unterscheidung ist in Perl unerheblich.

Allgemeine Deklaration

Aufbau

  sub SUBROUTINENNAME{
    DEKLARATIONSBLOCK      
    ANWEISUNGSBLOCK
    return RÜCKGABEWERT;
  }

Die Deklaration von internen Variablen einer Subroutine erfolgt entweder mit local oder mit my.

Beispiel:

my    $param1 = 0;
local $param2 = 0;

Bei der Verwendung von local steht die Variable auch untergeordneten Subroutinen zur Verfügung.

Die Parameterübergabe erfolgt in Perl nicht wie üblich im Kopfteil der Subroutine. Stattdessen steht das vordefinierte Array @_ zur Verfügung.

Beispiel:

my    $param1 = $_[0];
local $param2 = $_[1];
...

Prototyp

Ein Prototyp hat die Aufgabe, dem Hauptprogramm den Namen und die Parametertypen mitzuteilen. Er schreibt sich wie ein reduzierter Kopfteil einer Subroutine.

Beispiel, Subroutine mit zwei einfachen Übergabeparametern und einem optionalen einfachen Übergabeparameter:

  sub SUBROUTINENNAME($$;$)

Beispiel, Subroutine mit einer Übergabeliste:

  sub SUBROUTINENNAME(@)

Aufruf

Subroutinen werden mit dem Symbol & gefolgt vom Namen der Subroutine aufgerufen.

 Möglichkeit 1:
 &SUBROUTINENNAME(PARAMETERLISTE);
 Möglichkeit 2:
 SUBROUTINENNAME(PARAMETERLISTE);
 Möglichkeit 3:
 &SUBROUTINENNAME PARAMETERLISTE;
 

Bei Verwendung eines Prototyps oder einer Paket-Subroutine gibt es auch noch die

 Möglichkeit 4:  
 SUBROUTINENNAME PARAMETERLISTE;

Subroutinen lassen sich ohne und mit Parameterlisten aufrufen. Die Parameter finden sich innerhalb der Subroutine in der Struktur @_ wieder und können mit $_[] ($_[0], $_[1] ... usw.) separat angesprochen werden.

Beispiel:

sub groesser{
    if ($_[0] > $_[1]){
        $_[0]; #ergebnis
    }else{
        $_[1]; #ergebnis = rueckgabewert
    }
}

Aufruf mit &groesser(24,15) liefert als Ergebnis 24. ($_[0]=24 der Rückgabewert).

Mit lokalen Variablen:

sub groesser{
    local ($a,$b) = ($_[0],$_[1]);
    if ($a > $b){
        $a;
    }else{
        $b;
    }
}

Dieses Beispiel liefert das gleiche Ergebnis wie das vorhergehende.

Das in C, C++ und anderen Programmiersprachen verwendete return zur Rückgabe eines einzelnen Wertes ist in Perl am Ende einer Subroutine nicht zwingend nötig. Von der Subroutine wird immer der Rückgabewert des letzten Befehls zurück gegeben. Die folgende Subroutine test liefert zum Beispiel den Wert 1, da dieser bei erfolgreicher Ausführung der festgelegte Rückgabewert von print ist.

sub test{
    print "Nichts zu tun.\n\n";
}


Kontext

Eine Besonderheit in Perl ist, dass der Rückgabewert einer Subroutine nicht nur von den Parametern abhängt, sondern auch vom Kontext, in dem der Aufruf erfolgt. Deshalb sind solche Unterprogramme keine Funktionen im strengen Sinne. Das Schlüsselwort sub in Perl ist von "subroutine" ("Unterprogramm") abgeleitet.

Den Kontext muss auch bei der Verwendung einiger eingebauter Subroutinen beachten werden, zum Beispiel bei der Verwendung der Subroutine each.

my %hash = (Kuh => 'Gras', Kamel => 'Wasser', Gnu => 'Freie Software');

while( my $tier,$topic = each(%hash) ){
    print $tier," => ",$topic,"\n"
}

while( my ($tier,$topic) = each(%hash) ){
    print $tier," => ",$topic,"\n"
}

Liefert die Ausgabe:

 => Gnu
 => Kamel
 => Kuh
Gnu => Freie Software
Kamel => Wasser
Kuh => Gras

Bei der zweiten Schleife liefert each durch die Klammer ein Schlüssel-Wert Paar. In der Schleife darüber wird der Variable $topic bei jedem Schleifendurchlauf ein Schlüsselwert zugewiesen.

Um dies in eigenen Subroutinen nutzen zu können, liefert die Perl-Subroutine wantarray einen wahren Wert, wenn als Rückgabe der aufrufenden Subroutine eine Liste erwartet wird.

Externe Subroutinen

Viele Subroutinen sind bereits in den vielen hundert Modulen im CPAN und anderswo als freie Software verfügbar. Um dabei Namenskonflikte zu vermeiden, werden zusammengehörige Subroutinen in einem Namensraum zusammengefasst.

Ein Beispiel ist das Modul File::Temp. Es verwendet den Namensraum File::Temp und enthält zwei Subroutinen, eine zur Erstellung von temporären Dateien (tempfile) und eine für Verzeichnisse (tempdir).

Namensräume sind in Perl hierarchisch aufgebaut und sollten vom Programmierer sinnvoll gewählt werden. Außerdem ist, wie man sieht, der Namensraum meist identisch mit dem Modul. Umfangreiche Module können aber auch viele Namensräume nutzen.

Der gewählte Name sollte in einem Zusammenhang mit der Funktion des Moduls stehen. So stehen alle Module im Namensraum File in einem Zusammenhang mit Dateien.

Laden eines Moduls mit use

 use File::Temp;

In dieser Form wird das Modul während der Übersetzungszeit geladen. Außerdem wird eine spezielle Subroutine in dem zu ladenden Modul aufgerufen. Ihr Name ist import.

 use File::Temp ();

Schreibt man hinter das Modul eine leere Liste, wird der Aufruf von import übergangen.

 use File::Temp qw/ tempfile tempdir /;

Für Experten: In dieser Form zeigt sich woher die Bezeichnung use stammt. Subroutinen können häufig in den aktuellen Namensraum geladen werden, sie werden quasi importiert. Genau das soll mit dieser Form von use ausgedrückt werden.

Erstellung

Bibliothek

Eine Bibliothek ist eine Datei, die Subroutinen enthält. Der Dateiname endet mit *.pm, und die letzte Zeile ist:

 1;
Modul

Einbindung und Aufruf

Eine Bibliothek wird mit require eingebunden:

require("DATEINAME.pl");

Subroutinen aus Bibliotheken werden wie interne Subroutinen aufgerufen.

Ein Modul wird mit use eingebunden

use MODULNAME;

und mit

  MODULNAME::SUBROUTINENNAME();

aufgerufen.


Einfache Beispiele für den Einstieg

Fallunterscheidung

Ein Beispiel für eine if/elseif/else-Struktur

#!/usr/bin/perl -w
# if/elsif/else
# 20041110
  
if (1233 > 2333) {
    print "Ergebnis 1\n";
}
elsif (3333 > 4444) {
    print "Ergebnis 2\n";
} 
else {
    print "Ergebnis 3\n";
}
  
# ergibt: Ergebnis 3
# das selbe ohne if/elsif/else (TIMTOWTDI-Prinzip)
  
print "Ergebnis ", 1233 > 2333 ? 1 : 3333 > 4444 ? 2 : 3, "\n";

Ein Beispiel für den Vergleich von Strings

#!/usr/bin/perl -w
# Stringvergleich eq, ne (equal, not equal)
  
if ("huhu" eq "huhu") {
    print "beide Zeichenketten gleich";
}

if ("wiki" ne "books") {
    print "strings sind unterschiedlich";
}

Vergleiche mit String-Variablen

#!/usr/bin/perl
#@potbot
#Vergleich mit Variablen/String (If/else)
#Usereingabe mit -> String-Variable

print"Wie heißt der Erfinder dieser schönen Sprache?\n";

$userinput=<STDIN>;                              # Variable in der die Usereingabe gespeichert wird. <STDIN>=Standard-Input.
$var1='Larry Wall';                              # Vergleichsvariable mit dem String-Wert 'Larry Wall'.
chomp($userinput);                               # Chomp entfernt den Zeilenumbruch von der Usereingabe. Wichtig!
                                                 
if ($userinput eq $var1){                        # String-Vergleiche immer mit 'eq'(equal) oder 'ne'(not equal).
print"Richtige Antwort! :D\n";                  
}
else {                                           
print"Hmm, wer hat denn hier nicht aufgepasst?! ;D\n";
}

#--~~~~

Ein weiteres Beispiel

#!/usr/bin/perl -w
# 20041110
  
print "1+1 = 4\n" if 1+1 == 2;

something else

#!/usr/bin/perl -w
print "\aAlarm\n";                              # \a gibt einen Piepton aus, es folgt die Zeichenkette 'Alarm'
                                                # und \n gibt eine neue Zeile aus;
print `hostname`;                               # fuehrt das Kommando "hostname" in einer Shell aus und liest
                                                # die Standardausgabe der Shell und zeigt diese als Resultat
                                                # an. "hostname" ist also kein Perl-Befehl!;

$var0 = "0123456789";
print substr($var0, 3, 5);                      # gibt '34567' aus; substr holt aus $var0 von Zeichen nr.3 die 
                                                # darauf folgenden 5 Zeichen und gibt sie aus ...;

Dateihandling

Ausgabe des Inhaltes von $text in die Datei test.txt

 #!/usr/bin/perl
 print "Wie heißt Du? ";
 #aus der Standardeingabe lesen
 $text = <STDIN>;
 #letztes Zeichen von $text (\n) entfernen
 chomp($text);
 open(file, ">test.txt") or die "Fehler beim Öffnen der Datei: $!\n";
 #$text in file schreiben
 print file $text;
 close (file) or die "Fehler beim Schließen von 'test.txt': $! \n";

Umwandlung in HTML

Funktion zur Umwandlung von Umlauten in deren HTML-Äquivalente. Alternativ können diese mit dem Zusatzparameter '2' auch in der Doppellautschreibweise dargestellt werden. Die ganze Funktion kann in eine Bibliotheks-Datei im cgi-bin-Verzeichnis ausgelagert werden, um dann bei Bedarf von allen CGI-Perl-Dateien mit "require" eingebunden zu werden.

sub umlautwechseln {
    my $return = $_[0];          # erster Parameter
    my $matchcode = $_[1];       # zweiter Parameter
    if(!defined($matchcode)) {
        $matchcode = 1;
    }

    my @vorlage = (
        ['ä',      'ö',      'ü',      'Ä',      'Ö',      'Ü',      'ß'],
  	['&auml;', '&ouml;', '&uuml;', '&Auml;', '&Ouml;', '&Uuml;', '&szlig;'],
  	['ae',     'oe',     'ue',     'Ae',     'Oe',     'Ue',     'ss']
    );

    my $vorlage = 0;
    for (my $i=0; $i<=6; $i++) {                           # alternativ: for ( 0 .. 6 )
        while ( index($return, $vorlage[0][$i], 0) > -1 ) {
            substr ($return, index($return, $vorlage[0][$i], 0), 1) = $vorlage[$matchcode][$i];
        }
    }

    return $return;
}

1;

Das selbe Beispiel könnte ebenfalls mit Regular-Expressions gelöst werden, wie man im folgenden Beispiel sehen kann:

#!/usr/bin/perl
use strict;
use warnings;

sub umlautwechseln {
    my $messystring = shift;
    my $conversion = shift || "1";

    my @vorlage = (
        [   'ä',   'ö',      'ü',      'Ä',      'Ö',     'Ü',      'ß'],
        ['&auml;', '&ouml;', '&uuml;', '&Auml;', '&Ouml;','&Uuml;', '&szlig;'],
        [   'ae',  'oe',     'ue',     'Ae',     'Oe',    'Ue',     'ss']
    );

    for (0 .. 6) {
        $messystring =~ s/$vorlage[0][$_]/$vorlage[$conversion][$_]/g;
    }

    return $messystring;
}

Erläuterung der Funktion:

Diese Funktion erwartet 2 Parameter, wobei der zweite Parameter optional ist ( $conversion ). Falls der zweite Parameter nicht angegeben wird, wird der Wert "1" angenommen. Der erste Parameter ist der Skalar mit den Sonderzeichen.

In Zeile 16 erfolgt die eigentliche Arbeit. $messystring wird mittels RegEx untersucht und entsprechende Treffer werden ersetzt.

Erzeugung von SQL-Code

Dieses Script kann genutzt werden für die Beispieldatenbank der Einführung in SQL. Es erzeugt etwas mehr als 100.000 SQL-Anweisungen für MySQL, die mit einer Kanalumleitung in die Beispieldatenbank eingespielt werden können, und dort jeweils einen Datensatz erzeugen.

Hinweis: Die Tabellen wurden inzwischen geändert, siehe Anmerkungen zur Beispieldatenbank. Bitte beachten Sie, dass im Laufe der Arbeit mit Änderung der Datenbankstruktur weitere Spalten angelegt werden und danach auch dafür Werte benötigt werden.

Glasbutton Warnung.svg

Für die Beispieldatenbank fehlen Datensätze für die Tabellen Fahrzeug und Versicherungsnehmer. In der jetzigen Version des folgenden Skripts werden die Bedingungen der Fremdschlüssel (ForeignKeys) verletzt.

Für Perl-Neulinge von Interesse sind vermutlich eher

  • die Verwendung der ForEach-Schleife,
  • die alternative Textausgabe, die besonders für längere Texte geeignet ist,
  • der alternative Zugriff auf die Datenbank, der ohne das DBI-Modul auskommt.
 #!/usr/bin/perl

 use strict;

 my @namen=("Meyer", "Müller", "Schulze", "Schneider", "Schubert", "Lehmann", 
  "Bischof", "Kretschmer", "Kirchhoff", "Schmitz", "Arndt");
 my @vornamen=("Anton", "Berta", "Christoph", "Dieter", "Emil", "Fritz", "Gustav", 
  "Harald", "Ida", "Joachim", "Kunibert", "Leopold", "Martin", "Norbert", "Otto", 
  "Peter", "Quentin", "Richard", "Siegfried", "Theodor", "Ulf", "Volker", "Walter", 
  "Xaver", "Yvonne", "Zacharias");
 my @orte=("Essen", "Dortmund", "Bochum", "Mülheim", "Duisburg", "Bottrop", 
  "Oberhausen", "Herne", "Witten", "Recklinghausen", "Gelsenkirchen", 
  "Castrop-Rauxel", "Hamm", "Unna", "Herten", "Gladbeck");
 my $orte="";
 my @strassen=("Goethestr.", "Schillerstr.", "Lessingstr.", "Badstr.", "Turmstr.", 
  "Chausseestr.", "Elisenstr.", "Poststr.", "Hafenstr.", "Seestr.", "Neue Str.", 
  "Münchener Str.", "Wiener Str.", "Berliner Str.", "Museumsstr.", "Theaterstr.", 
  "Opernplatz", "Rathausplatz", "Bahnhofstr.", "Hauptstr.", "Parkstr.", 
  "Schlossallee");
 my @gesellschaften=("Zweite allgemeine Verabsicherung", "Sofortix 
  Unfallversicherung", "Buvaria Autofutsch", "Provinziell", "Vesta Blanca");
 my @beschreibungen=("Standardbeschreibung Nr 502", "08/15", "Blablabla", 
  "Der andere war schuld!", "Die Ampel war schuld!", "Die Sonne war schuld!", 
  "Die Welt ist schlecht!!");
 my $beschreibungen="";
 my $gesellschaften=0;
 my $gebdat="";
 my $fdat="";
 my $hnr=0;
 my $eigen="";

 foreach my $ort (@orte) {
   my $gplz=int(rand(90000))+10000;
   foreach my $strasse (@strassen) {
     my $plz=$gplz+int(rand(20));
     foreach my $name (@namen) {
       foreach my $vorname(@vornamen) {
         $gebdat=dating(80, 1907);
         $fdat=dating(80, 1927);
         $hnr=int(rand(100))+1;
         if(rand(2)>1) {$eigen="TRUE";} else {$eigen="FALSE";}
         my $vers=int(rand(5));

 print <<OUT1
 insert into VERSICHERUNGSNEHMER(NAME, VORNAME, GEBURTSDATUM, 
 FUEHRERSCHEIN, ORT, PLZ, STRASSE, HAUSNUMMER, 
 EIGENER_KUNDE, VERSICHERUNGSGESELLSCHAFT_ID) values ("$name", 
 "$vorname", "$gebdat", "$fdat", "$ort", "$plz", "$strasse", "$hnr", "$eigen", 
 "$vers");
 OUT1
 }}}}

 for(my $a=0; $a<=500; $a++)
 {
   my $udat=dating(3, 2004);
   my $ort=$orte[int(rand(16))];
   my $beschreibung=$beschreibungen[int(rand(7))];
   my $shoehe=int(rand(20000000))/100;
   my $verletzte;
   if(rand(2)>1) {$verletzte="TRUE";} else {$verletzte="FALSE";}
   my $mitarbeiter=int(rand(10))+1;
 print <<OUT2
 insert into SCHADENSFALL(DATUM, ORT, BESCHREIBUNG, 
 SCHADENSHOEHE, VERLETZTE, MITARBEITER_ID) values 
 ("$udat", "$ort", "$beschreibung", $shoehe, "$verletzte", $mitarbeiter);
 OUT2
 }

 for(my $a=1; $a<=500; $a++)
 {
   my $vne=int(rand(100000))+1;
 print <<OUT3
 insert into ZUORDNUNG_SF_FZ(SCHADENSFALL_ID, FAHRZEUG_ID) values 
 ($a, $vne);
 OUT3
 }

 sub dating
 {
   my $range=$_[0];
   my $radix=$_[1];
   my $y=int(rand($range))+$radix;
   my $m=int(rand(12))+1;
   my $d=int(rand(28))+1;
   my $return=$y . "-" . $m . "-" . $d;
   return $return;
 }


Fortgeschrittene Themen

Programmierstil und -struktur

Kommentare

Kommentare sollten gut und reichlich verwendet werden. Es ist kein Fehler, wenn das Verhältnis zwischen Kommentaren und effektivem Code bei 1:1 liegt. Da man in Perl sehr kompakten Code schreiben kann, ist bei veröffentlichtem Code vom CPAN ein Verhältnis 2:1 und darüber völlig normal.

Zu unterscheiden sind dabei die zwei verschiedenen Formen von Kommentar, die Perl erlaubt.

Die einfachste Form ist die Kommentarzeile, die alles hinter dem #-Zeichen bis zum Zeilenende beinhaltet. Daneben unterstützt Perl von Haus aus ein Werkzeug für eingebettete Dokumentation. Dieses trägt den Titel Plain Old Documentation oder kurz POD. Es erlaubt ähnlich WikiSyntax einfache Formatierungen und Verknüpfungen.

Direkt nach der Shebang-Zeile sollte der Programmname aufgeführt werden. Das ist hilfreich, weil man häufig mit less oder more sich mehrere Quelltexte in Folge zu Gemüte führt, und man sich so orientieren kann, in welchem Skript man sich gerade befindet. Das ist auch praktisch, wenn man die Möglichkeit hat, Programmlistings auf Endlospapier zu drucken.

Anschließend sollte eine ausführliche Programmbeschreibung inline in den Quelltext eingearbeitet werden. Bei Teamprojekten ist es außerdem sinnvoll, den Namen des Autors zu hinterlegen, sowie Modifikationen festzuhalten mit Beschreibung der Modifikation, Datum und Name des modifizierenden Autors.

Häufig ist es außerdem sinnvoll, Unterfunktionen, Schleifen und Verzweigungen mit beschreibenden Kommentaren zu bedenken. Meilensteine/Wendepunkte in der Programmlogik sollten mit einem markierenden/benennenden Kommentar versehen werden. Auch wichtige Variablen sollten mit einem Kommentar beschrieben werden.

Der Deklarationsteil

Die Variablendeklaration sollte der Übersichtlichkeit halber ausschließlich zu Beginn der Funktion (bei der Hauptfunktion zu Beginn des Programms) erfolgen. Die Programmlogik sollte sich klar vom Deklarationsteil abheben, und diesem nachfolgen.

Variablen sollten in erster Linie lokal innerhalb der Funktionen verwendet werden. Globale Variablen sollten auf das absolut nötige Mindestmaß beschränkt bleiben. Wenn ein Fehler auf eine Variable zurückgeführt werden kann, dann schränkt sich der zu durchsuchende Quelltextbereich auf diese Weise extrem ein.

Die Variablenbezeichnung sollte, trotz des Mehraufwandes beim Tippen, nicht kryptisch, sondern verständlich sein. $countkunden, $countmitarbeiter und $countlieferanten sagt mehr als $ck, $cm und $cl, vor allem, wenn der Chef sagt, dass man das Programm mal für vier Wochen links liegen lassen soll, weil eine wichtige Auftragsarbeit anliegt.

use strict;

Wie schon beim "Hello World!"-Programm angedeutet, sollte der Perl-Programmierer grundsätzlich die Anweisung

use strict;

verwenden. Dadurch zwingt er sich selber, nur Variablen zu verwenden, die er vorher deklariert hat. Der augenfälligste Vorteil dabei ist, daß der Programmierer eine Fehlermeldung erhält, wenn ihm bei der Verwendung einer Variablen ein Tippfehler unterläuft. Unterlässt er dies, kann sich das in sehr merkwürdigen und unvorhergesehenen Programmabläufen und stunden- bis tagelangen Fehlersuchen äußern.

use warnings;

Mit dem Pragma „warnings“ werden in dem aktuellen Block Warnungen an- und abgeschaltet. Ohne dieses Pragma führt Perl stillschweigend viele Operationen durch, die der Programmierer so nicht gemeint, aber leider eingegeben hat. In folgendem Beispiel hat sich ein Tippfehler eingeschlichen:

  my $summe = "1:" + 2;

Ohne „use warnings“ wird die Operation stillschweigend durchgeführt. Mit diesem Pragma erfährt der Programmierer, dass etwas nicht stimmt:

use warnings;
my $summe = "1:" + 2;

ergibt die Warnung

 Argument "1:" isn't numeric in addition (+) at -e line 2.

Dieses Pragma ist in den manpages warnings und perllexwarn erläutert. In perldiag sind alle Warnungen aufgeführt, die Perl ausgibt.

selbstdefinierte Funktionen

Sobald sich Programmschritte wiederholen, sollten diese in eine Funktion ausgelagert werden. Damit wird der betreffende Code an einer Stelle zusammengefasst und nicht mehrfach über ein Programm verteilt. Die Fehlersuche und -behebung erleichtert dies ungemein, da dann nur in dieser einen Funktion gesucht werden muss und nicht an den vielen Stellen, die durch ein Kopieren eines Programmabschnittes entstanden sind.

Eine Funktion sollte wie ein gutes Werkzeug nur einen Zweck erfüllen, diesen aber dafür sehr gut. Dieser Zweck sollte sich in einem treffenden Namen niederschlagen.

Eine Funktion sollte wenn möglich auf keine nicht lokalen Variablen zugreifen und allein über ihre Argumente gesteuert werden.

Eine Funktion sollte mit POD dokumentiert werden. Dies ist unabhängig davon, ob sie exportiert wird oder nur zur internen Verwendung gedacht ist. Vermutlich wird der Autor der Funktion nach sechs Monaten nicht mehr wissen, warum er oder sie genau diesen Code für den Zweck gewählt hat, daher sollte dies kommentiert werden.

Querverweise: Siehe auch Perl-Programmierung: Subroutinen, Kommentar von Funktionen (in Perl-Programmierung: POD), nicht lokale Variablen (in Perl-Programmierung: Variablen)


Perl::Tidy

Um Perl-Code automatisch zu formatieren gibt es das praktische Werkzeug Perl::Tidy.

Logging

Bei wirklich umfangreichen Projekten ist ein Einsatz der Bibliotheken Log::Dispatch und Log::Log4Perl empfehlenswert, sie stellen ein ausgereiftes Logging Framework zur Verfügung. Eine kurze Einführung vom Author des letztgenannten Moduls ist hier zu finden: http://perlmeister.com/snapshots/200301/index.html .

Vorerst aber kann man es umgehen, sich dort einzuarbeiten. Völlig ausreichend bei mittelgroßen Projekten ist es, unterschiedlichste Laufzeitergebnisse in eine Log-Datei umzuleiten. Bei mir hat sich folgender, vielleicht noch ausbaufähiger Usus entwickelt:

Schritt 1:

#Deklarationsteil
my $loglevel=5;

Schritt 2:

#Anfang der Programmlogik
open (LOG, ">laufzeitausgaben.log") || die "Blabla\n";

.
.
.

#Ende der Programmlogik
close(LOG);

Schritt 3:

#Mitten in der Programmlogik
if($loglevel>4) {print LOG "VARIABLE 1: ". $variable1 . "\n";}

#oder
if($loglevel>6) {print LOG "VARIABLE 2: ". $variable2 . "\n";}

In diesem Beispiel würde die erste Logausgabe zugelassen, die zweite unterdrückt. Diese Möglichkeit ist erwünscht.

Mit dem numerischen Wert wird jeder Logausgabe eine Priorität zugewiesen, je wichtiger, desto kleiner. Mit einer kleinen Änderung im Deklarationsteil kann ab jetzt der Loglevel bestimmt werden, und damit der Detail-Grad der Logausgaben. Ohne groß zu stören, können die Ausgabezeilen jetzt im Quelltext verbleiben, bis sie gebraucht werden.



Gültigkeitsbereich von Variablen

Allgemeines

In einigen Punkten ist Perl einfacher gestrickt als andere Programmiersprachen, was den Gültigkeitsbereich von Variablen betrifft ist dies jedoch nicht zutreffend. Dabei muss unterschieden werden, zwischen dem Bereich in dem der Variablenname gültig ist und dem Bereich in dem der Inhalt verfügbar ist. Diese beiden Bereiche sind nur für lexikalische Variablen unter bestimmten Bedingungen identisch, nämlich nur dann, wenn keine weitere Referenz auf den Wert der Variable angelegt wurde.

In Perl muss man sich, wie in der Einleitung zu den Variablen erklärt, weniger Gedanken darum machen, ob der Wert auf den ein Variablenname verweist noch gültig ist, da die Speicherverwaltung fast vollkommen selbständig von perl übernommen wird. Nur bei rekursiven Datenstrukturen muss man dafür sorgen, dass der Speicher am Ende der Lebensdauer wieder freigegeben wird, da der Referenzzähler nicht von selbst wieder auf 0 gesetzt wird.

Für Variablen findet man in imperativen Programmiersprachen die Unterscheidung in globale, das heißt im ganzen Programm gültige Variablen und lokale, nur in einem begrenzten Block zum Beispiel einer einzelnen Funktion gültige Variablen. Um Perl zu verstehen, muss man wissen, dass Perl für die Verwaltung seiner Variablen zwei verschiedene Bereiche kennt.

Es gibt die mit dem Schlüsselwort my deklarierten lexikalischen Variablen. Ein andere Beschreibung für sie sind statisch gebundene Variablen, da der Gültigkeitsbereich nach der Deklaration nicht mehr geändert werden kann. Ein solcher Bereich kommt in Perl in verschiedenen Formen vor. Es kann ein Codeblock, eine Funktion, ein eval Aufruf oder einfach eine Datei sein. Ein direkter Zugriff von außerhalb des Bereichs auf diese Variablen ist ebenfalls nicht möglich.

Das Gegenstück dazu sind die dynamisch gebunden Variablen. Diese werden innerhalb der Namensräume verwaltet. Die Lebensdauer wird von Perl nicht beschränkt so dass man hier auch von globalen Variablen spricht.

Aus diesem Grund und weil bei lexikalischen Variablen der Zugriff ein wenig schneller erfolgt, sollte diese Form den Vorzug erhalten.

Für die globalen Variablen bietet Perl mit dem Schlüsselwort local die Möglichkeit den Wert der Variable auf einen bestimmten Bereich des Programms begrenzt zu verändern. Die Änderung geht beim Verlassen des Bereichs verloren. Das ist der gewünschte Effekt, denn so sind globale Variablen sinnvoller einsetzbar, da sichergestellt ist, dass der ursprüngliche Wert für alle anderen Teile des Programms, wieder hergestellt wird.

Auch wenn in den folgenden Beispielen meist Skalare verwendet werden, gilt das in diesem Kapitel gesagte ebenso für Arrays und Hashes.

Globale Variablen

Für das Anlegen globaler Variablen gibt es wie üblich in Perl gleich mehrere Möglichkeiten. Die erste und einfachste Variante, die jedoch in der Praxis nicht zu empfehlen ist, besteht darin, das Pragma strict nicht zu verwenden.

package Irgendwie::Irgendwo;

$hier = "Großstadt";

package Irgendwie::Sowieso;

$hier = 'Kuhdorf';

package main;

print "Viele leben in der $Irgendwie::Irgendwo::hier und beneiden die Landeier im $Irgendwie::Sowieso::hier,";

Benutzt man dann eine Variable, so hat man die Variable im Namensbereich des aktuellen package definiert. Der qualifizierte Name der Variablen lautet also $Irgendwie::Irgendwo::hier und $Irgendwie::Sowieso::hier.

use strict "vars";

Jetzt funktioniert das nicht mehr sondern der Variablenname muss vor der Verwendung bekannt gemacht werden. Dafür gibt es auch wieder zwei Wege. Der ältere, den man nutzen sollte, falls es darauf ankommt, dass die Programme auch mit Versionen vor 5.6 laufen, sieht so aus:

use vars qw/$hier $da/;

Mit perl 5.6 wurde das Schlüsselwort our eingeführt, das fast genau denselben Effekt hat.

package Irgendwann;
use strict;

{
    our $zeit;
}

sub verlauf {
    our $zeit;
    ...
}

Normalerweise wird einer Variable bei ihrer Deklaration ein Wert zugewiesen. Entweder explizit im Programm mittels einer Wertzuweisung

our $gestern="heute";

oder implizit durch Perl, nämlich undef für Skalare und die leere Liste bzw. Hash für Listen und Hashes.

our @tage       # entspricht ()
our %sonnentage # ebenso

Existiert eine dynamisch gebundene Variable bereits, wird eine weitere Deklaration mit our, keine implizite Wertzuweisung vornehmen. Das ist sicher auch das Verhalten, welches von einer globalen Variable erwartet werden kann. Man kann so gefahrlos innerhalb einer Funktion (wie in dem Beispiel "verlauf") die Deklaration wiederholen. Sie ist dann nur für alle, die den Programmtext studieren müssen, ein Hinweis darauf, woher diese Variable kommt und dass es sich um eine Paketvariable handelt.

Perlkenner werden es vermuten beziehungsweise wissen, dass es noch andere Möglichkeiten gibt, globale Variablen zu erstellen. Eine ist der ersten vorgestellten Möglichkeit sehr ähnlich und besteht darin, den vollständigen Variablennamen anzugeben. Dieser besteht aus dem Paketnamen und dem eigentlichen Variablennamen.

$Irgendwie::Irgendwo::hier = "ein kleines Dorf";

Diese Variante sollte aber nur dann eingesetzt werden, wenn es keine andere Möglichkeit gibt, da in diesem Fall die Schutzmechanismen, die use strict vor Schreibfehlern bietet, nicht greifen. Nötig ist diese Art, auf eine Variable zuzugreifen, immer dann, wenn von einem anderen Namensraum aus auf eine Variable zugegriffen wird. Außerdem ist bei dieser Form zu beachten, dass zwar die Variable erstellt, aber der Name nicht bekannt gemacht wird. Nur $hier ohne Paketname ist für den Übersetzungsvorgang eine noch nicht deklarierte Variable und würde bei aktiviertem use strict einen Fehler bedeuten.

Das Perl-Standardmodul Exporter bietet eine Möglichkeit, Variablennamen zu exportieren, also den Variablennamen für einen anderen Namensraum nutzbar zu machen. Damit kann eine Variable von mehreren Paketen gemeinsam genutzt werden, ohne immer den vollständigen Paketnamen angeben zu müssen. Es wird dafür im aktuellen Paket ein Alias erzeugt, um auf die Variable zuzugreifen.

Lokale Variablen

Eine solche Variable hat nur in dem Bereich Gültigkeit in dem sie deklariert wurde. Zu diesem Zweck werden überwiegend lexikalisch gebundene Variablen eingesetzt. Theoretisch könnte man zwar auch mit our eine lokale Variable erstellen. Der Übersetzer beschränkt, ebenso wie bei my die Gültigkeit des Variablennamens auf den aktuellen Block. Am Ende des Blocks müsste die Variable vom Programm aber explizit wieder aus dem Namensraum gelöscht werden. Dieser Aufwand wird nur selten notwendig sein.

Lexikalische Variablen in einem inneren Block überdecken gleichnamige Variablen eines umschließenden Blocks.

Temporäre Wertänderung einer globalen Variable

Das Schlüsselwort local wird verwendet, um Wertänderungen einer globalen Variablen temporär zu begrenzen. Beim Verlassen des Sichtbarkeitsbereiches wird der alte Wert der Variablen wiederhergestellt. Vor der Einführung von lexikalischen Variablen wurde local oft verwendet. Heutzutage gibt es nur wenige sinnvolle Anwendungen. Haupteinsatzzweck ist die temporäre Änderung von Spezialvariablen.

open my $fh, '<', '/tmp/many_lines.txt';
my $inhalt;
                       # Lesen ist zeilenbasiert
{
  local $/ = undef;    # Lesen ist jetzt nicht mehr zeilenbasiert
  $inhalt = <$fh>;
}
                       # Lesen ist wieder zeilenbasiert, da $/ im obrigen Block lokalisiert war
close $fh;

Äquivalent könnte man obiges auch so implementieren:

open my $fh, '<', '/tmp/many_lines.txt';
my $inhalt;
while (<$fh>) {
    $inhalt .= $_;
}
close $fh;

Siehe auch File::Slurp.


Reguläre Ausdrücke

Einleitung

Als erstes stellt sich die Frage, was Reguläre Ausdrücke (kurz: regex) sind und was man mit ihnen machen kann. Zum anderen warum sie gerade in einem Perl-Buch erklärt werden.

Reguläre Ausdrücke sind eine Art Mini-Programme. Sie wurden entwickelt, um das Arbeiten mit Texten komfortabler und leichter zu gestalten. Reguläre Ausdrücke sind vergleichbar mit "Mustern" oder "Schablonen", die auf einen oder mehrere unterschiedliche Strings passen können. Diese Muster können entweder auf einen String passen oder nicht passen.

Hierbei existieren zwei Kategorien von Regulären Ausdrücken. Einmal eine normale Mustersuche, zum anderen eine "Suche und Ersetze"-Funktion. Die normale Mustersuche wird zum einen darin verwendet, um ganze Eingaben oder Strings zu überprüfen oder einzelne Informationen aus einen String auszulesen. Die Suchen- und-Ersetzen-Funktion hat dabei eine ähnliche Funktion, wie Sie es von grafischen Texteditoren gewohnt sind, nur sind diese in Perl deutlich mächtiger.

Die englischen Begriffe für die Muster- und "Suche & Ersetze"-Funktion sind dabei: "Pattern matching" und "Substitution". Diese Begriffe sollte man kennen, da sie oft benutzt werden. Diese werden hier ebenfalls im weiteren Verlauf Verwendung finden.

Zum anderen stellt sich immer noch die Frage, was das Ganze mit Perl zu tun hat. Reguläre Ausdrücke werden deshalb behandelt, da sie ein zentraler Bestandteil von Perl sind. Sie werden in Ihrer Perl-Karriere wohl kein Perl-Programm finden, in dem nicht mindestens ein Regulärer Ausdruck vorkommt. Reguläre Ausdrücke sind dabei so fest in Perl verankert und wurden im Laufe der Zeit so stark ausgebaut, dass dieses viele andere Programmiersprachen kopierten. Sie werden Reguläre Ausdrücke in Sprachen wie: PHP, Java, C#, Python, JavaScript, Tcl, Ruby und noch vielen weiteren Programmiersprachen finden. Dabei wird diese Erweiterung meist als "Perl-kompatibel" beschrieben. Jedoch sind Reguläre Ausdrücke in keiner dieser Sprachen so fest implementiert und so leicht anzuwenden wie in Perl.

Man kann schon fast sagen, dass Reguläre Ausdrücke erst durch Perl ihre heutige Funktionalität bekommen haben.

Dabei reißt der Artikel die Möglichkeiten von diesen Ausdrücken nur an.


Der Aufbau der beiden genannten Typen sieht dabei folgendermaßen aus:

Pattern Matching:

 m/Regex/Optionen

Substitution:

 s/Regex/String/Optionen

Begrenzer

Wie man am Pattern Matching sowie der Substitution erkennen kann, trennen die Slashes "/" die einzelnen Teile eines Regulären Ausdruckes. Allerdings haben Sie bei Perl die Wahl, jedes beliebige Sonderzeichen als Begrenzer zu wählen. Die Vorteile davon werden Sie zu schätzen wissen, wenn Sie praktische Erfahrung mit Regulären Ausdrücken sammeln. Um es kurz vorweg zu sagen: Sie haben damit die Wahl ein Zeichen zu wählen das nicht in Ihrer Regex vorkommt, und Sie können sich somit das Maskieren der Zeichen sparen.

Perl weiß anhand des ersten Zeichen, das nach dem "m" oder dem "s" folgt, welcher Begrenzer gewählt wurde. Es sind also auch folgende Schreibweisen erlaubt:

 m!regex!
 s#Regex#String#Optionen
 s$Regex$String$Optionen
 s"Regex"String"Optionen
 ...

Eine spezielle Regel gilt für Zeichen, die ein öffnendes sowie schließendes Zeichen besitzen. Denn dort müssen die einzelnen Teile eingeklammert werden. Dies schaut folgendermaßen aus:

 m(Regex)
 s(Regex)(String)Optionen
 s{Regex}{String}Optionen
 s<Regex><String>Optionen
 s[Regex][String]Optionen

Wie man sieht werden hier unterschiedliche Anfangs- sowie Endzeichen verwendet. Eine weitere Eigenschaft ist, dass nur das wirkliche Endzeichen die Regex respektive den String einklammert. Im folgenden praktischen Beispiel ist also auch folgendes möglich:

 s((H)allo)(Welt)i

Wenn Sie etwas Erfahrung mit Regulären Ausdrücken haben, werden Sie sehen, dass diese Regex keinen Sinn ergibt. Allerdings dient das lediglich zur Veranschaulichung, dass hier wirklich "(H)allo" als Regex erkannt wird, und nicht "(H" wie man annehmen könnte.

Wenn Sie noch nicht verstehen, was hier passiert, dann ist dies nicht weiter schlimm, wir werden später darauf zurückkommen.

Bindungsoperator

Wie die Form eines Regulären Ausdrucks ausschaut, wissen Sie. Jedoch wissen Sie noch nicht, wie man diesen auf einen String anwendet. Hierfür existiert der sogenannte Bindungsoperator. Um einen String mit einer Regex zu verbinden, egal ob nun "Pattern Matching" oder "Substitution", schreiben Sie einfach folgendes:

$text =~ m/Regex/;
$text =~ s/Regex/String/;

Dieser Bindungsoperator prüft im ersten Fall, ob in $text das angegebene Muster auf der rechten Seite vorkommt. Zur Substitution kommen wir noch später; allerdings sei hierzu gesagt, dass jedes Vorkommen der angegebenen Regex in $text durch String ersetzt wird.

Weiterhin besitzt dieser Ausdruck einen Rückgabewert. Wenn das Muster, das in Regex angegeben wird, wirklich in $text passt, dann wird "true" zurückgegeben. Das gleiche gilt für die Substitution. Wenn die Regex auf $text gepasst hat, wurde eine Ersetzung durchgeführt und es wird der Wert "true" zurückgegeben.

Sollte die Regex in beiden Fällen nicht auf den String in $text gepasst haben, dann wird "false" als Wert zurückgeliefert. Bei der Substitution hat dies noch die Auswirkung, dass eine Ersetzung nicht stattgefunden hat.

Grundlegendes zu Regulären Ausdrücken

In diesem Kapitel, erfahren Sie grundlegende Einzelheiten wie Reguläre Ausdrücke funktionieren. Sie werden einzelne Stolpersteine kennenlernen, und lernen sie zu vermeiden. Nach diesem Kapitel sollten Sie in der Lage sein Reguläre Ausdrücke auf beliebige Strings anzuwenden, und nur das zu finden, zu ersetzen oder die Informationen zu extrahieren die Sie wollen.


Pattern Matching

Mit dem jetzigen Wissen wollen wir ein Pattern Matching ausführen. Wir wollen nach einem bestimmten Wort in einem String suchen, und sofern gefunden, wollen wir dies dem Benutzer mitteilen.

Ein konkretes Beispiel:

1 $string = "Wir mögen Kamele, auch wenn sie übel riechen";
2 if ($string =~ m/Kamel/)
3 { print "Kamel gefunden!"; }
4 else
5 { print "Schade, kein Kamel weit und breit."; }

Die Ausgabe des Perl-Scripts wäre "Kamel gefunden". Gehen wir die einzelnen Zeilen zusammen durch. In Zeile 1 wird ein Skalar mit dem Text "Wir mögen Kamele, auch wenn sie übel riechen" definiert. Zeile 2 ist nun neu für uns. Hier wird der Rückgabewert von unserem Ausdruck "$string =~ m/Kamel/" in einer bedingten Anweisung (if) ausgewertet. Wie wir wissen, wird "true" zurückgegeben, wenn unser Suchmuster in $string vorkommt. Wenn unser Suchmuster nicht vorkommt, wird "false" als Wert zurückgegeben. Dies hat direkte Auswirkung auf unsere if-Kontrollstruktur. Wenn unser Muster gefunden wird, dann wird "true" zurückgegeben und dadurch Zeile 3 ausgeführt. Wenn das Muster nicht in $string vorkommt, wird "false" zurückgegeben und Zeile 5 ausgeführt.

Aber warum finden wir denn überhaupt unser "Kamel"? Im String steht doch "Kamele". Dies ist zwar richtig, aber Perl interessiert sich nicht für Wörter. Perl liest unser Muster folgendermaßen: Ein "K", gefolgt von "a", gefolgt von "m", gefolgt von "e", gefolgt von "l". Unser komplettes Muster wird also an folgender unterstrichener Stelle gefunden.

 Wir mögen Kamele, auch wenn sie übel riechen

An diesem Punkt wird unsere Suche auch sofort abgebrochen. Was danach kommt ist unwichtig. Unsere Regex hat auf das Muster gepasst und es wird als Rückgabewert "true" zurückgegeben.


Hier haben wir 2 Sachen gelernt:

  • Die Mustersuche erkennt lediglich ein Zeichen nach dem anderen, ohne einen höheren Zusammenhang, also z.B. ein Wort daraus bilden zu können.
  • Die Mustersuche wird sofort beendet sobald unsere Regex vollständig passt.


Zwei wichtige Punkte, auf die Sie später immer wieder stoßen werden. Wissen Sie, was ausgegeben werden würde, wenn Sie den Ausdruck in der oberen if-Kontrollstruktur folgendermaßen anpassen würden?

$string =~ m/kamel/

Richtig! Es würde "Schade, kein Kamel weit und breit." ausgegeben werden! Warum? Perl interpretiert die Mustersuche folgendermaßen: Ein kleines "k", gefolgt von einem kleinen "a", gefolgt von einem kleinen "m" ...


Also nochmals zur Verdeutlichung. Es werden wirklich nur Folgen von Zeichen erkannt, ohne diese zu Interpretieren. Ein großes "K" ist ein anderes Zeichen als ein kleines "k" und wird folglich nicht gefunden. Da im ganzen $string kein "k" gefolgt von "a" ... vorkommt wird letztendlich "false" als Wert zurückgegeben, und unser "else"-Block wird ausgeführt.


Allerdings brauchen Sie keine Angst haben, dass Sie jetzt jede Schreibweise von "Kamel" ( "kAmEl", "KAMel", ... ) überprüfen müssen. Es gibt bestimmte Optionen die Sie aktivieren können, wodurch eine Groß- und Kleinschreibung nicht unterschieden wird.

Substitution

Bevor wir uns nun mit den Optionen befassen, wollen wir eine Substitution durchführen. Hierfür passen wir das vorherige Beispiel etwas an:

1 $string = "Wir mögen Kamele, auch wenn Kamele übel riechen";
2 $string =~ s/Kamel/Lama/;
3 print $string;

In Zeile 1 wird ein String initialisiert, danach führen wir eine Substitution auf $string aus. Dort wollen wir "Kamel" durch "Lama" ersetzen. Unser Ergebnis wird danach zurückgegeben.

Wissen Sie bereits was zurückgegeben wird? Denken Sie erst darüber nach, bevor Sie sich die Lösung anschauen:

 Wir mögen Lamae, auch wenn Kamele übel riechen

Überrascht? Gehen wir die Substitution einzeln durch. Unsere Substitution sagt, dass wir das Vorkommen von einem großen "K" gefolgt von einem kleinen "a" ... durch "Lama" ersetzen wollen. Wir müssen also jedes Vorkommen von "Kamel" erst einmal finden, und es danach durch "Lama" ersetzen. Damit wir unser "Kamel" überhaupt finden, beginnt unsere Substitution an der ersten Stelle unseres Strings. Hier wird überprüft ob das "K" auf das "W" von "Wir" passt. Das passt natürlich nicht, also springen wir ein Zeichen weiter. Es wird nun überprüft ob das "i" auf das "K" passt. Dies passt natürlich nicht, und unsere Substitution geht so lange den String weiter, bis es auf das erste "K" von "Kamel" passt. Jetzt ist gefordert, dass ein "a" folgt. Dies kommt wirklich vor, und die Substitution springt ein Zeichen weiter, solange bis unser ganzes "Kamel" erkannt wurde. Nun ist unsere Regex erfolgreich erkannt worden, und unser "Kamel" wird durch "Lama" ersetzt. Wichtig ist, dass unser folgendes "e" von "Kamele" nicht erkannt wurde, da wir nicht wissen wie wir Wörter erkennen können (jedenfalls noch nicht). Die Ersetzung wird also durchgeführt, und unsere Substitution war erfolgreich. Es wird "true" als Rückgabewert zurückgeliefert, und die Substitution beendet. Allerdings wird der Rückgabewert "true" verworfen. Unsere Substitution dringt erst gar nicht bis zum zweiten "Kamele" vor, und ersetzt dieses auch nicht, weil unsere Substitution bereits vorher erfolgreich war.

Hier lernen wir also wieder einige Neuigkeiten:

  • Ein String wird von links nach rechts durchgearbeitet.
  • Es wird immer der frühestmöglichste Treffer links gefunden.


Um jetzt jedes Vorkommen vom "Kamel" durch "Lama" zu ersetzen, könnten wir folgendes schreiben:

1 $string = "Wir mögen Kamele, auch wenn Kamele übel riechen";
2 while ($string =~ s/Kamel/Lama/) {}
3 print $string;

Wenn also unser "Kamel" gefunden und erfolgreich ersetzt wurde, wird als Rückgabewert "true" geliefert. Diese Rückgabe bringt while dazu, die leere Schleife noch einmal anzustoßen. Anschließend wird erneut unsere Bedingung durchgeführt. Zu beachten ist, dass unsere Substitution wieder ganz von vorne beginnt, also an der ersten Stelle im String anfängt, und nicht an der Stelle, an der wir zuletzt etwas verändert haben. Da das erste "Kamel" bereits beim ersten Durchlauf durch "Lama" ersetzt wurde, findet und ersetzt die Substitution trotzdem das zweite Vorkommen von "Kamel". Manchmal ist dieses Verhalten gewünscht, aber in den seltesten Fällen ist dies der Fall, und es kann hierbei zu Problemen kommen. Stellen Sie sich folgendes while Konstrukt vor:

while ( $string =~ s/e/ee/ ) {}

Hiermit hätten wir eine Endlossschleife gebaut. Das erste Vorkommen eines "e" wird durch ein "ee" ersetzt. Der Rückgabewert ist true und unsere Substitution beginnt wieder von vorne. Jetzt sind zwei "e" an der Stelle vorhanden, und dort ersetzen wir wieder das erste "e" durch "ee". Es existieren also schon 3 "e" an dieser Stelle. Dieses wird jetzt unendlich oft durchgeführt. Jedenfalls solange bis Perl abstürzt, weil Sie nicht genügend RAM haben um so einen großen String zu speichern.

Sie sollten also aufpassen bei solch einer Verwendung. Es gibt zwar eine Option, die unserem gewünschten Verhalten entspricht und bei der letzten Substitution weitermacht. Aber manchmal benötigen wir das obige Verhalten.

Optionen

Optionen dienen dazu das Verhalten unserer Regex zu verändern. Mit ihnen sind Sachen möglich, die so ohne weiteres nicht möglich wären. Jede Option kann dabei unsere Regex grundlegend verändern. Die Optionen werden hierbei hinter den Regulären Ausdruck angehängt. Es ist auch möglich mehrere Optionen zu benutzen, die Reihenfolge der Optionen spielt hierbei keine Rolle. Den grundlegenden Aufbau sehen Sie in der Einleitung, hier aber nochmals ein paar praktische Beispiele:

m/kamel/i
m/k a m e l/xi
s/kamel/lama/ig
s/k a m e l/igx

Einige wichtige Optionen sollen hierbei bereits erläutert werden, andere wenn sie wichtig werden:

Option: /i

Mit der Option "i" ignore-case können wir Perl dazu veranlassen, dass zwischen Groß- und Kleinschreibung nicht mehr unterschieden wird. Folgendes Muster:

  m/kamel/i

Würde also auch auf "KAMEL", "KAmel", "KaMeL", ... passen.

Option: /g

Im Kapitel "Substitution" wollten wir, dass jedes Vorkommen von "Kamel" durch "Lama" ersetzt wird, bei der folgenden Lösung mit der while-Schleife funktionierte das zwar, jedoch könnte dieses unter Umständen zu neuen Problemen führen. Das "g" steht hier für global und es möchte damit ausdrücken, dass wir den ganzen String durcharbeiten. Genau gesagt bewirkt "/g", dass die Substitution nach einer Ersetzung nicht beendet wird, sondern an der letzten Position weiter macht, und nach weiteren Treffern sucht. Der Rückgabewert ist hierbei die Anzahl von Substitutionen, die innerhalb des Strings durchgeführt wurden. Wenn also mindestens eine Substitution durchgeführt wurde, ist der Rückgabewert automatisch "> 0" und somit ein "wahrer" Wert.

Hierbei ist zu beachten, dass die Option nur Auswirkung auf eine Substitution hat. Wir können z.B. nicht mit:

$string =~ m/e/g;

Die Anzahl der "e" Buchstaben innerhalb eines Strings zählen.

Dadurch, dass unsere Substitution jedoch nicht immer wieder von vorne anfängt, können wir das letzte Problem im Kapitel "Substitution" lösen.

1 $string = "Wir mögen Kamele, auch wenn Kamele übel riechen";
2 $string =~ s/e/ee/g;
3 print $string;

Dies würde nun nicht mehr in eine Endlosschleife enden, sondern folgenden String zurückgeben:

 Wir mögeen Kameelee, auch weenn Kameelee übeel rieecheen
Option: /x

Normalerweise werden innerhalb einer Regex Whitespace-Zeichen als zu dem Muster gehörend angesehen.

m/a b/

Diese Regex würde auf ein "a" gefolgt von einem Leerzeichen gefolgt von einem "b" passen. Mit dieser Option verliert das Leerzeichen seine Bedeutung, und wir würden ein "a" gefolgt von einem "b" suchen.

Unter Whitespace-Zeichen versteht man alle Zeichen, die nicht direkt etwas auf dem Bildschirm Zeichnen. Dies sind zum Beispiel Leerzeichen, Tabulatoren, Newlines und Formfeeds.

Wahrscheinlich werden Sie den Sinn dahinter noch nicht nachvollziehen können. Für die sehr kleinen Regexe, die wir bisher geschrieben haben, ist dieses auch unbrauchbar. Allerdings werden wir später auf sehr viel komplexere Regexe stoßen. Damit diese besser lesbar sind, wurde diese Option implementiert. Damit kann man eine Regex über mehrere Zeilen verteilen und ihnen sogar Kommentare geben.

Zusammenfassung
  • "i", case-insensitive: Groß- und Kleinschreibung wird ignoriert
  • "g", global: Es werden alle Stellen gesucht, die passen. Die Funktion ist eher für das Ersetzen mit regulären Ausdrücken interessant.
  • "m", multi-line: Verändert die Bedeutung des $-Zeichen (siehe Sonderzeichen), damit es an der Position vor einem "\n" passt.
  • "s", single-line: Verändert die Bedeutung des .-Zeichen (siehe Sonderzeichen), damit es auch auf einem "\n" passt.
  • "x", extended: Alle Whitespace-Zeichen innerhalb des Regulären Ausdrucks verlieren ihre Bedeutung. Dadurch kann man Reguläre Ausdrücke optisch besser aufbereiten und über mehrere Zeilen schreiben.
  • "o", compile once: Ausdruck wird nur einmal kompiliert und kann nicht mehr verändert werden.
  • "e", evaluate: Das Ersetzmuster wird als Perl-Code interpretiert und ausgeführt.

Quantoren

Quantoren sind eine Möglichkeit auszudrücken, dass etwas bestimmt oft nacheinander folgt. Hierbei kann man die Anzahl selber bestimmen, oder man benutzt bereits vordefinierte Quantoren. Diese vordefinierten Quantoren wurden eingebaut, weil diese besonders oft vorgekommen sind. Sie werden durch Sonderzeichen definiert. Quantoren beziehen sich immer auf die Einheit die vor ihnen steht. Dies kann dabei ein einfacher Buchstabe, ein Zahl oder aber auch eine Gruppierung von Zeichen sein.

Stellen Sie sich vor, Sie möchten eine Folge von 15 "a" hintereinander erkennen. Sie könnten in Ihrer Regex das a nun 15mal schreiben, allerdings können Sie sich dabei leicht verzählen. Genauso wird es schwieriger Ihren Code zu Lesen. Daher wäre die Benutzung eines Quantors ideal.

m/a{15}b/i

Wie man erkennen kann, wird ein Quantor durch geschweifte Klammern definiert. Da sich der Quantor auf die vorherige Einheit bezieht, wird hier gesagt, dass das "a" 15 mal vorkommen muss. Der Quantor bezieht sich hier nicht auf das "b", wie man annehmen könnte. Was wäre aber, wenn wir nun eine Mindestgrenze und eine Maximalgrenze angeben wollen? Dies wäre auch kein Problem.

m/a{10,15}b/i

Hiermit sagen wir, dass das "a" mindestens 10 mal vorkommen muss und maximal 15 mal vorkommen darf. Danach muss ein "b" folgen. Nun wollen wir aber das ein "a" nur eine mindestgrenze erfüllen muss, es danach aber unendlich oft folgen darf. Um dies auszudrücken, lassen wir einfach die Maximalgrenze weg.

m/a{10,}b/i

Wichtig hierbei ist, dass das Komma stehen bleiben muss. Würden wir das Komma weg lassen, hätten wir eine genaue Angabe wie oft das "a" vorkommen muss. In diesem Beispiel muss das "a" nun mindestens 10 mal hintereinander vorkommen, darf aber auch unendlich oft vorkommen. Das Gleiche können wir auch für die Maximalangabe machen.

m/a{,10}b/i

Hiermit würde wir ein "a" maximal 10 mal finden, allerdings darf es auch kein einziges mal vorkommen.

Quantor: ?

Dieser Quantor ist identisch mit {0,1}. Er drückt aus, dass das vorherige optional ist, d.h. 1-mal oder keinmal vorkommen darf.

m/\.html?/i

Dies würde z.B. auf die Dateiendung ".htm" sowie auch ".html" passen. Der Punkt muss hier durch ein "Backslash" maskiert werden, da der Punkt eine besondere Bedeutung hat. Genauso wie das Fragezeichen. Wollen Sie nicht die besondere Bedeutung des Fragezeichen haben, weil Sie nach einem Fragezeichen suchen wollen, müssen Sie dieses auch maskieren. Durch "\?" verliert das Fragezeichen seine Bedeutung als Quantor. Dies gilt ebenfalls für alle anderen Sonderzeichen.

Quantor: *

Dieser Quantor ist identisch mit {0,}. Er drückt aus, dass das vorherige beliebig häufig vorkommen darf, also auch keinmal. Dieser Quantor wird erst interessant mit sogenannten Zeichenklassen.

m/\d*/i

Hier greife ich etwas vorweg. Das "\d" steht dabei für eine beliebige Ziffer von 0-9. Wenn wir den Stern-Quantor auf das "\d" anwenden, dann finden wir eine Folge von Ziffern. Allerdings muss keine Ziffer an dieser Stelle stehen, denn keinmal ist ja ebenfalls erlaubt. Bei der Verwendung des Sterns müssen Sie aufpassen. Nicht immer ist es das, was Sie wollen. Er würde auch auf "zweiundvierzig" passen, da es nunmal auch erlaubt ist, wenn keine Ziffer vorkommt.

Quantor: +

Der Quantor ist identisch mit {1,}. Er drückt aus, dass das vorherige mindestens einmal vorkommen muss, aber unendlich oft folgen darf. Wie auch der Stern-Quantor ist dieser erst mit einer Zeichenklassen interessant.

m/\d+/i

Meistens ist es das, was Sie wollen. Es erkennt eine beliebige Anzahl von Ziffern. Dabei muss jedoch mindestens eine Ziffer vorkommen.

Gierigkeit

Vielleicht haben Sie sich bei dem "?"-Quantor gefragt, was nun als erstes erkannt wird. Das "htm" oder das "html". Alle Quantoren die hier vorgestellt wurden sind gierig. Das bedeutet, dass, wenn sie die Wahl haben ein Zeichen zu erkennen oder nicht zu erkennen, sie es immer zuerst versuchen werden, es zu erkennen.

Bei dem Beispiel mit dem "?"-Quantor würde zuerst das ".htm" erkannt werden. Das "l" ist Optional, da es aber gierig ist, schaut es nach, ob das "l" wirklich danach kommt, und wird es ebenfalls aufnehmen wenn es folgt. Wenn es nicht folgen sollte, ist unsere Regex ebenfalls erfüllt, da es auch erlaubt war, wenn das "l" nicht auf ".htm" folgt.

Zeichenklasse

Manchmal möchten Sie, dass an einer bestimmten Stelle eine Auswahl unterschiedlicher Zeichen stehen kann. Für dieses Problem gibt es die sogenannten Zeichenklassen. Eine Zeichenklasse wird mit eckigen Klammern umgeben. Hierbei ist zu beachten, dass die komplette Zeichenklasse für ein einziges Zeichen steht. Innerhalb der Zeichenklasse wird definiert, auf welches Zeichen die Zeichenklasse passen darf.

m/[234][12345]/

Dieses Matching würde auf eine zweistellige Zahl passen. Dabei muss die erste Ziffer 2, 3 oder 4 sein, und die zweite Ziffer 1, 2, 3, 4 oder 5. 50 oder 20 würden z.B. nicht gefunden werden.

Zeichenklassen-Metazeichen

Innerhalb von Zeichenklassen ist der Bindestrich als sogenanntes Zeichenklassen-Metazeichen erlaubt. Hiermit können wir ganze Bereiche von Zeichen angeben. Wollen wir z.B. alle Zahlen erkennen, können wir das auf zwei Arten tun.

 [0123456789]
 [0-9]

Diese beiden Zeichenklassen erkennen genau das gleiche. Bei Buchstaben wird der Vorteil offensichtlicher:

 [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]
 [a-zA-Z]

Möchten wir ein Bindestrich innerhalb einer Zeichenklasse erkennen, dann müssen wir diesen als erstes Zeichen schreiben.

 [-a-zA-Z]

Dies würde auf alle Buchstaben inklusive des Bindestriches passen.

Negative Zeichenklasse

Weiterhin gibt es eine negative Zeichenklasse. Dort können wir definieren, auf welche Zeichen unsere Zeichenklasse nicht passen darf. Möchten wir eine negative Zeichenklasse verwenden, dann muss das erste Zeichen innerhalb der Zeichenklasse ein Zirkumflex (^) sein. Wenn das Zirkumflex nicht an erster Stelle steht, wird es als normales Zeichen erkannt.

Wenn also jedes beliebige Zeichen außer einer Zahl erkannt werden soll, können wir folgendes schreiben:

 [^0-9]

Zeichenklassen

Dieser Abschnitt ist sehr verwandt mit der Zeichenklasse. Während wir bei der Zeichenklasse unsere Zeichen wählen konnten, können wir dies bei den Zeichenklassen nicht mehr. Diese Zeichenklassen dienen lediglich als Abkürzung für eine bestimmte Zeichenklasse:

  • \d = digit Erkennt Ziffern. Ist das gleiche wie [0123456789]
  • \D = Erkennt alles andere außer Ziffern. Ist das gleiche wie [^0123456789]
  • \s = Erkennt jegliche Art von Whitespace-Zeichen: Leerzeichen, Tabulatoren, Newlines, Formfeed ...
  • \S = Erkennt alles außer Whitespace-Zeichen.
  • \w = word Erkennt Ziffern, Buchstaben und Unterstrich. Ist das gleiche wie [a-zA-Z0-9_]
  • \W = Erkennt alles außer einem Wortzeichen.
  • . = Punkt Steht für jedes Zeichen außer Newline. Ist das gleiche wie [^\n]

Alternation

Unter Alternation verstehen wir dass entweder das eine, oder das andere passen kann. Es ist also eine "Oder"-Verknüpfung. Eine Alternation schreiben wir als "|" (Pipe) Zeichen. Hierbei wird dann entweder das genommen was links von diesem Zeichen steht, oder was rechts von diesem Zeichen steht.


Pattern Matching

Bei der Alternation innerhalb des Pattern Matching gibt es wenig zu beachten. Stellen Sie sich vor, Sie schreiben ein Programm und möchten, dass sich das Programm nach diversen Eingaben des Benutzers beendet. Sie könnten folgendes Schreiben

1 $input = <STDIN>;
2 if ( $input =~ m/q|quit|exit/i ) { exit; }
3 print "Hallo, Welt!\n";

Dieses Programm wartet auf eine Eingabe des Benutzers. Würden wir "q", "quit" oder "exit" eingeben, dann würde sich unser Programm beenden. Bei allem anderen würden wir die Meldung "Hallo, Welt!" auf dem Bildschirm sehen.

Substitution

Innerhalb einer Substitution gibt es einige Punkte die wir beachten müssen. Stellen Sie sich vor, Sie möchten jedes vorkommen von "q" oder "quit" durch "exit" ersetzen. Vielleicht würden Sie so etwas schreiben:

s/q|quit/exit/ig;

Dies funktioniert aber nicht richtig. Sollte wirklich "quit" im String vorkommen auf dem Sie diese Regex anwenden, dann würde folgendes dabei raus kommen:

 exituit

Um die genaue Vorgehensweise zu verstehen, müssen Sie wissen wie Perl eine Alternation behandelt. Es wird wieder Zeichen für Zeichen überprüft. Dabei wird aber auch die Reihenfolge der Alternation beachtet. Es wird zuerst der Ausdruck ganz links überprüft und erst wenn dieser nicht passt, wird der nächste Ausdruck überprüft. Sollte ein Ausdruck passen, wird sofort die Substitution ausgeführt. Bei "quit" passt das "q" sofort und es würde hier eine Substitution mit "exit" statt finden. Dadurch würde ein "quit" nie im Text ersetzt werden, da wir schon vorher das "q" durch "exit" ersetzt haben. Wir müssen also die Reihenfolge vertauschen:

s/quit|q/exit/ig;


Merke:

  • Bei der Alternation ist die Reihenfolge wichtig

Dieser Punkt gilt auch für das Pattern Matching, allerdings hängt es von der Verwendung ab, ob wir die Reihenfolge anpassen müssen. Im obrigen Beispiel ist es egal wodurch unser Programm beendet wird. Würden wir aber Informationen auslesen, kann es sehr wohl von Bedeutung werden, welche Reihenfolge wir in der Alternation gewählt haben.

Sonderzeichen

Für die Suchmuster stehen diverse Sonderzeichen zur Verfügung. Diese können dann beispielsweise für beliebige Zeichen oder für das Zeilenende stehen.

  • . steht für ein beliebiges Zeichen außer dem "\n".
  • ? steht für das ein- oder nullmalige Vorkommen des vorangegangenen Zeichens oder Gruppierung. Folgt das Fragezeichen auf einen Quantor dann wird dieser zu einem nicht gierigen Quantor.
  • + steht für das ein- oder mehrmalige Vorkommen des vorangegangenen Zeichen oder Gruppierung.
  • * steht für das null- oder mehrmalige Vorkommen des vorangegangenen Zeichen oder Gruppierung.
  • ^ steht für den Beginn einer Zeile.
  • $ steht für das Ende eines Strings. Wenn die /m Option benutzt wird, wird die Bedeutung so verändert das es für ein "\n" Zeichen steht.
  • \A steht für den Beginn eines Strings.
  • \Z steht immer für das Ende eines Strings, unabhängig ob die Option /m verwendet wurde.
  • \ - das nächste Zeichen wird ohne Funktion interpretiert. Um einen Punkt zu suchen muss "\." benutzt werden, sonst wird ein beliebiges Zeichen gefunden.
  • [] wird Zeichenklasse genannt und steht für ein angegebenes Zeichen. [dhb]ot würde "dot", "hot" oder "bot" finden.
  • () 1. Funktion: Gruppiert Ausdrücke. 2.Funktion: Speichert den tatsächlichen Wert, der an dieser Stelle gefunden wurde, in einer Variable.
  • | steht für das logische ODER. "ist|war" gibt sowohl true, wenn "ist" im Ausdruck vorkommt, als auch wenn "war" im Ausdruck enthalten ist.

Zeichen ersetzen

(todo)

Zeichen ersetzen ohne Reguläre Ausdrücke

Geht es nur darum, einzelne Zeichen durch andere zu ersetzen, sind Reguläre Ausdrücke häufig 'überqualifiziert', da es mit tr/// eine deutlich einfachere und performantere Alternative gibt.

$string =~ tr/SUCHEN/ERSETZEN/Optionen

SUCHEN und ERSETZEN sind dabei Auflistungen der zu ersetzenden Zeichen und ihren entsprechenden Ersetzungen. tr/abc/xyz/ ersetzt alle a mit x, alle b mit y und alle c mit z.

Zusätzlich zu einzelnen Zeichen können Bereiche angegeben werden. Ist die Liste ERSETZEN kürzer als die Liste SUCHEN, werden die übrigen Zeichen von SUCHEN mit dem letzten Zeichen von ERSETZEN ersetzt. Die beiden Ausdrücke tr/a-f/xyz/ und tr/abcdef/xyzzzz/ bewirken also das Gleiche.

Einige nützliche Beispiele:

$string =~ tr/A-Z/a-z/;                 # ersetzt alle Großbuchstaben durch Kleinbuchstaben
$string =~ tr/A-Z!-\/:-@[-`{-~/a-z /;   # ersetzt zusätzlich ASCII-Sonderzeichen durch Leerzeichen
$string =~ tr/A-Za-z/N-ZA-Mn-za-m/;     # im Usenet häufig verwandte ROT13-Chiffre

Als Rückgabewert der Operation wird die Anzahl der gefunden Zeichen verwendet. Damit gibt es auch die Möglichkeit, mit tr/// Zeichen in einem String zu zählen. Dazu verwendet man die gleichen Sequenzen für SUCHEN und ERSETZEN, oder die Liste der ersetzenden Zeichen wird einfach leergelassen:

# Zählt die Vokale im String
$anzahlVokale = ($string =~ tr/AEIOUaeiou//);


Objektorientiert Programmieren in Perl

Deklaration einer Klasse in Perl

Klassen werden in Perl nicht deklariert, sondern es werden nur Methoden einer Klasse definiert. Wenn eine Methode definiert wird, ordnet der Compiler die Methode dem aktuellen Paket zu. Ein Paket wird durch die Funktion package eingeleitet.

  package MeineKlasse;

Kapselung

Eigenschaft

Eigenschaften gehören zu einer Instanz, und nicht zu einer Klasse.

Erstellung und Aufruf einer Methode in Perl

package MeineKlasse;

# Methode definieren
sub meineklassenmethode { 
  print "Die Ausführung meiner Klassenmethode ist gelungen!!"; 
}

# Methode aufrufen
MeineKlasse::meineklassenmethode();

Konstruktor-Methoden in Perl

Ein Konstruktor ist eine Methode, die dabei mithilft, eine Instanz einer Klasse zu erzeugen. In Perl gibt es keine zwingenden Vorschriften, wie diese benannt wird. Gewöhnlich wird diese "new" genannt, und wir empfehlen, diesen Gebrauch beizubehalten.

package MeineKlasse;

# Konstruktor definieren
sub new { 
  my $invocant=shift;

  # wurde Konstruktor von Instanz- oder
  # von der Klasse aufgerufen?
  my $class=ref($invocant) || $invocant;

  # Instanz ist eine Hashreferenz
  my $self={};

  # Hashreferenz zur Instanz machen
  bless $self, $class;
  print "Die Instanz wurde erzeugt!!"; 

  # Instanz zurückgeben
  return $self
}


Die Destruktor-Methode in Perl

Für den Destruktor ist der Methodenname DESTROY zwingend vorgegeben. Der Destruktor ist aber nur notwendig, wenn bei der Auflösung einer Instanz noch besondere Anweisungen ausgeführt werden sollen.

Der Destruktor wird aufgerufen, sobald der garbage collector eine nicht mehr referenzierte Instanz gefunden hat und ihren Speicher freigeben möchte. Möchte man vor der Freigabe noch Handlungen durchführen, wie zum Beispiel das Schließen von Dateien oder das Kappen von Datenbankverbindungen, so muss man dies im Destruktor tun.

Die Reihenfolge, in der Destruktoren aufgerufen werden, hat nichts mit der Reihenfolge zu tun, in der die Instanzen nicht mehr refenziert werden. Auf die Reihenfolge des Destruktoraufrufs kann und soll sich der Programmierer nicht verlassen.

Erzeugung einer Instanz

Mit Hilfe des Konstruktors ist es möglich, eine Instanz einer Klasse zu erzeugen:

Wertebelegung von Instanzeigenschaften

privat und öffentlich

Vererbung in Perl

{ 
  package meineunterklasse;
  @ISA=("meineklasse");
}

@ISA ist kein Skalar, sondern ein Array. Damit ist sichergestellt, dass Kindklassen in Perl mehrere Elternklassen haben können.

Polymorphie

Überlagerung einer Klassenmethode in Perl

{ 
  package meineunterklasse;
  @ISA=("meineklasse");
  sub meineklassenmethode { 
    print "Die Ausführung meiner überlagerten Klassenmethode ist gelungen!!"; 
  }
}


Vordefinierte Variablen

Vordefinierte Variablen

Perl bietet eine Reihe von vordefinierten Variablen, die vom Perl-Interpreter automatisch deklariert werden. In den Variablen werden Informationen über die Laufzeitumgebung und das Perl-Skript gespeichert.

Verschiedene Skalarvariablen

Um die alternativen Variablennamen nutzen zu können, muss das Modul English importiert werden:

use English;


$^O Hier wird das Betriebssystem angegeben (alternativ: $OSNAME)
$^T Gibt - in Unix-Zeitrechnung - den Zeitpunkt, zu dem das Programm gestartet wurde, an (alternativ: $BASETIME)
$^W Ob der Perl-Interpreter mit der Option -w gestartet wurde (alternativ: $WARNING)
$0 Name des Skripts (alternativ: $PROGRAM_NAME)
$< Gibt an, unter welcher BenutzerInnen-Kennung (User-ID) das Skript gestartet wurde (alternativ: $UID)
$( Die Gruppenkennung (Group-ID), unter das Skript ausgeführt wird (alternativ: $GID)
$$ Die Prozess-ID des Programms (alternativ: $PID)

$UID und $GID funktionieren nicht unter Windows!

Umgebungs-Variablen

Über den Hash %ENV kann auf die Umgebungsvariablen (environment) eines Betriebssystems zugegriffen werden Aufruf:

foreach (keys(%ENV)){
    print $_ . ": " . $ENV{$_} . "\n";
}

Mögliche Ausgabe unter Windows:

USERPROFILE: C:\Dokumente und Einstellungen\Test 
HOMEDRIVE: C:
TEMP: C:\DOKUME~1\TEST~1\LOKALE~1\Temp
SYSTEMDRIVE: C:
PROCESSOR_REVISION: 2302
SYSTEMROOT: C:\WINDOWS
COMMONPROGRAMFILES: C:\Programme\Gemeinsame Dateien
COMSPEC: C:\WINDOWS\system32\cmd.exe
SESSIONNAME: Console
LOGONSERVER: \\NEO
OSTYPE: cygwin32
APPDATA: C:\Dokumente und Einstellungen\Test\Anwendungsdaten
WINDIR: C:\WINDOWS
PROGRAMFILES: C:\Programme
OS: Windows_NT
CYGNUS_HOME: C:\Programme\cygwin
PROCESSOR_LEVEL: 15
PATHEXT: .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
USERNAME: Test
PROMPT: $P$G
NUMBER_OF_PROCESSORS: 2
FP_NO_HOST_CHECK: NO
HOMEPATH: \Dokumente und Einstellungen\Test
PROCESSOR_IDENTIFIER: x86 Family 15 Model 35 Stepping 2, AuthenticAMD
PATH: C:\Programme\cygwin\bin;C:\Perl\site\bin;C:\Perl\bin;C:\WINDOWS\system32; C:\WINDOWS;C:\WINDOWS\System32\Wbem;;C:\PROGRA~1\GEMEIN~1\MUVEET~1\030625
USERDOMAIN: NEO
GPC_EXEC_PREFIX: C:\Programme\cygwin/lib/gcc-lib/
COMPUTERNAME: NEO
ALLUSERSPROFILE: C:\Dokumente und Einstellungen\All Users
PROCESSOR_ARCHITECTURE: x86
TMP: C:\DOKUME~1\TEST~1\LOKALE~1\Temp

Kommandozeilenparameter

In der Listenvariablen @ARGV werden die Kommandozeilenparameter, die beim Aufruf angegeben wurden, gespeichert.
Aufruf:

perl beispiel.p -h

Anwendung:

#!/usr/bin/perl
use strict;
use warnings;

my $arg = shift @ARGV;
if ( ! defined $arg ) {
    print "Es wurde kein Argument übergeben.\n";
}
elsif ($arg eq '-h') {
   print "Leider ist noch keine Hilfe verfügbar.\n";
}
else {
   print "Der Parameter '$arg' ist nicht bekannt.\n";
}

Es gibt auf CPAN mehrere Module die @ARGV auswerten. Am weitesten verbreitet ist das Module Getopt::Long.

Funktionsvariablen

Die beim Aufruf einer Funktion mitgegebenen Variablen werden in der Liste @_ gespeichert. Diese ähnelt in der Verwendung der oben beschriebenen @ARGV, welche an das Hauptprogramm mitgegebene Werte enthält

Beispiel

sub Addition{
   my $zahl1 = shift(@_);
   my $zahl2 = shift(@_);
   print "Die Summe ist" . ($zahl1 + $zahl2);
}

Fehlermeldungen

Die Variable $! wird benutzt, wenn eine Systemfunktion einen Fehler verursacht hat. $! enthält in diesem Fall die Fehlermeldung, die dem Perl-Programm zurückgegeben wurde

open(IN,"<nix.txt") or print $!;

Module

Im Array @INC ist der aktuelle Suchpfad für Module abgelegt. Im Hash %INC sind die aktuell geladenen Module abrufbar.

$_

Die Variable $_ wurde bereits im Kapitel Spezialvariablen von Perl ausführlich besprochen. Jedesmal, wenn bei Funktionen oder Schleifen keine Variablen angegeben werden, speichert der Interpreter die jeweiligen Werte in $_. Mithilfe von $_ lässt sich sehr kurzer, allerdings auch sehr unleserlicher Programmcode produzieren!

open $IN, "< text.txt" or die "Fehler: $!";
while(<$IN>){
    print;
}

Dieses Programm liest eine Datei ein und gibt ihren Inhalt zeilenweise aus.
Eine leserlichere Version desselben Programms wäre:

open $IN, "< text.txt" or die "Error: $!";
while(my $input = <$IN>){
    print $input;
}


Perl-Schnittstellen

Perl/TK

Perl/TK

Erstellen einer GUI

Zur Nutzung von Perl/Tk wird das Modul Tk benötigt.

  use Tk;
Beispiel 1

Eine neue Instanz wird mit der Funktion Mainwindow aufgerufen.

  my $Hauptfenster = MainWindow->new;

Zur Anzeige und Verwendung wird die Funktion MainLoop verwendet, deren Aufruf einfacher nicht sein kann.

  MainLoop;

Beispiel 1:

#!/usr/bin/perl
use Tk;
use strict;
my $mw = MainWindow->new;
$mw->title ("Perl/Tk - Erste Schritte");
$mw->configure (-width=>"640",-height=>"480");
MainLoop;
#das wars schon

Widgets

Als Gestaltungselemente grafischer Benutzeroberflächen stellt Tk sogenannte Widgets zur Verfügung. Sie sind der Kern der GUI-Programmierung mit Tk. Im Wesentlichen sind dies:

  • Das Frame-Widget zur Erzeugung von Containerwidgets. Diese sind unsichtbar, erlauben aber die Gruppierung diverser sichtbarer Widgets.
  • Das Menu-Widget und das Menubutton-Widget zur Erzeugung von Kopfzeilenmenüs.
  • Das Label-Widget zur Anzeige von Strings.
  • Das Entry-Widget zur Eingabe von Werten per Tastatur.
  • Das Text-Widget zur Anzeige und Bearbeitung von Texten.
  • Das Button-Widget als Befehlsschaltfläche.
  • Das Scrolled-Widget zur Erzeugung von Rollbalken.
  • Das Listbox-Widget zur Darstellung von mehreren Daten in einem Widget(in einer Box).

Geometriemanager

Um die Positionierung der Widgets zu erleichtern, stellt Tk Geometriemanager zur Verfügung.

  • pack verwendet die nächstmögliche Position innerhalb der Richtungen top, right, bottom, left.
  • grid positioniert Widgets innerhalb einer Tabelle anhand der übergebenen Tabellenposition
  • place gestattet eine Pixelgenaue Zuordnung.

Zu beachten ist, daß die direkt dem Hauptfenster oder einem Frame zugeordneten Widgets nicht mit vermischten Geometriemanagern angeordnet werden.

pack

Der Geometriemanager pack erlaubt die Anordnung der Widgets nach Richtungen, top,left und bottom,right.

Ausserdem werden sogenannte Anker gesetzt, die bei einer Grössenänderung des Hauptfenster die Widgets wie gewünscht in Position halten:

  pack Optionen:
  
  -side   {'left','right','top','bottom'}       , wo
  -anchor {'n','ne','nw','w','sw','s','se','e'} , der Anker
Beispiel 2 - Hauptfenster
messageBox in Beispiel 2

Beispiel 2:

#!/usr/bin/perl
use Tk;
my $mw = MainWindow->new;
#configure mit Fenstergroesse macht bei pack keinen Sinn
$mw->title ("Perl/Tk - Erste Schritte");
my $label1 = $mw->Label (-text=>"Mein Name");
my $entry1 = $mw->Entry (-width=>60);
my $button1= $mw->Button(-text=>"Exit",-command=>\&cmd_button);
$label1->pack (-side=>"left");
$entry1->pack (-side=>"left");
$button1->pack(-side=>"left");
        
sub cmd_button
{
   $mw->messageBox (-message=>"Programm wird beendet!");
   exit;
}
MainLoop;

Wenn man nun die Grösse des Fensters verändert, wandern die Widgets in einer Reihe links in der Mitte mit, was nicht immer erwünscht ist, darum werden zur Positionierung meist <Anchors> eingesetzt.

Beispiel 3 mit Ankern

Beispiel 3 mit Ankern:

#!/usr/bin/perl
use Tk;
my $mw = MainWindow->new;
#configure mit Fenstergroesse macht bei pack keinen Sinn
$mw->title ("Perl/Tk - Erste Schritte");
my $label1 = $mw->Label (-text=>"Mein Name");
my $entry1 = $mw->Entry (-width=>60);
my $button1= $mw->Button(-text=>"Exit",-command=>\&cmd_button);
$label1->pack (-side=>"left",-anchor=>'nw'); #Nordwest Ecke
$entry1->pack (-side=>"left",-anchor=>'nw');
$button1->pack(-side=>"left",-anchor=>'nw');
        
sub cmd_button
{
   $mw->messageBox (-message=>"Progamm wird beendet!");
   exit;
}
MainLoop;

Interessant ist nun die Frage wie bekommt man den Exit Button unter das Label und das Eingabefeld (Entry). Dazu stellt das MainWindow Frames zur Verfügung, die eine weitere Untergliederung innerhalb des Fensters erlauben. Es wird nun ein Frame erzeugt und das Label und Entry mittels der Option -in von pack innerhalb des Frames positioniert, der wiederum innerhalb des Hauptfensters angeordnet ist.

=>Frames können mit den Optionen -width,-height und -bg wie jedes Fenster in Ihrer Groesse und Hintergrundfarbe geändert werde

  pack option:
   
  -in     {Frame} Widgets in ein untergeordnetes Fenster einsortien
  -expand {0,1}   1= Widget nimmt restliche Breite des Fensters ein
  -fill   {'x','y','none','both'} expansion in 'x','y','keine' oder 'beide' Richtung(en)
Beispiel 4

Beispiel 4:

#!/usr/bin/perl
use Tk;
my $mw = MainWindow->new;
    
my $frame = $mw->Frame();
    
#configure mit Fenstergroesse macht bei pack keinen Sinn
$mw->title ("Perl/Tk - Erste Schritte");
my $label1 = $mw->Label (-text=>"Mein Name");
my $entry1 = $mw->Entry (-width=>60);
my $button1= $mw->Button(-text=>"Exit",-command=>\&cmd_button);
    
$frame->pack (-side=>"top");
     
#using -in
$label1->pack (-in=>$frame,-side=>"left",-anchor=>'nw'); #Nordwest Ecke
$entry1->pack (-in=>$frame,-side=>"left",-anchor=>'nw');
    
$button1->pack(-side=>"left",-fill=>"x",-expand=>1);
        
sub cmd_button
{
   $mw->messageBox (-message=>"Progamm wird beendet!");
   exit;
}
MainLoop;

Jetzt befindet sich der Button unterhalb des Frame mit dem Eingabefeld. Die Kombination der Optionen -fill und -expand führt dazu, das der Button die komplette Fensterbreite einnimmt.

grid

Der Geometriemanager grid erlaubt die Anordnung der Widgets tabellarisch in Zellen, beginnend in der linken oberen Ecke mit -row=0 -column=0. Außerdem ist das verbinden von Zellen möglich mit -rowspan und -columnspan. Des Weiteren können Widgets widerum in einer Zelle an Richtungen gebunden werden (-sticky). Die Untergliederung des in Layouts in Frames ist genauso wie in pack möglich.

  grid optionen:
  
  -row       {0..x} Nummer der Zeile
  -column    {0..x} Nummer der Spalte
  -rowspan   {2..x} Anzahl der zu zusammenzufassenden Zeilen
  -columnspan{2..x} Anzahl der zu zusammenzufassenden Spalten
  -sticky    {'n','s','e','w'} Kombinationen erlaubt (auch durch Komma getrennt} 
                               'ew' bzw. 'ns' zieht Widget auf komplette Zellenbreite (auch bei
                                              columnspan) bzw. Zellenhöhe (auch bei rowspan)

  -in               weitere Untergliederung mit Hilfe von Frames
Beispiel 5

Beispiel 5 mit grid:

#!/usr/bin/perl
use Tk;
my $mw = MainWindow->new;
#configure mit Fenstergroesse macht bei grid keinen Sinn
$mw->title ("Perl/Tk - Erste Schritte");
my $label1 = $mw->Label (-text=>"Mein Name");
my $entry1 = $mw->Entry (-width=>60);
my $button1= $mw->Button(-text=>"Exit",-command=>\&cmd_button);
    
$label1->grid (-row=>0, -column=>0);
$entry1->grid(-row=>0, -column=>1); # eine Spalte weiter rechts
$button1->grid(-row=>0, -column=>2);
        
sub cmd_button
{
   $mw->messageBox (-message=>"Progamm wird beendet!");
   exit;
}
MainLoop;

Das ergibt das gleiche Bild wie mit pack. Wenn jetzt der Button in die nächste Zeile soll, dann wird für $button einfach -row geändert:

   $button->grid (-row=>1,-column=>0);

soll der Button in der Mitte stehen und vielleicht noch die gesamte Fensterbreite in Anspruch nehmen:

   $button->grid (-row=>1,-column=>0,-columnspan=>2,-sticky=>'ew'); #zwei Spalten überbrücken, Ost bis West

Mit Frames ändert sich eigentlich nicht viel, $label und $entry werden im Frame mit grid plaziert, $button braucht keine columnspan mehr, da nur eine Spalte vom Frame beansprucht wird:

Beispiel 6

Beispiel 6:

#!/usr/bin/perl
use Tk;
my $mw = MainWindow->new;
my $frame = $mw->Frame();
#configure mit Fenstergroesse macht bei grid keinen Sinn
$mw->title ("Perl/Tk - Erste Schritte");
my $label1 = $mw->Label (-text=>"Mein Name");
my $entry1 = $mw->Entry (-width=>60);
my $button1= $mw->Button(-text=>"Exit",-command=>\&cmd_button);
    
$frame->grid (-row=>0,-column=>0);
    
$label1->grid (-in=>$frame,-row=>0, -column=>0);
$entry1->grid (-in=>$frame, -row=>0, -column=>1); # einer Spalte weiter rechts
$button1->grid(-row=>1, -column=>0,-sticky=>'ew');
        
sub cmd_button
{
   $mw->messageBox (-message=>"Progamm wird beendet!");
   exit;
}
MainLoop;


CGI: Web-Entwicklung in Perl

Einleitung

Das Common Gateway Interface ( CGI ) bietet die Möglichkeit, seine Scripts auf Webservern, welche diese Technologie unterstützen, auszuführen. Neben Perl können solche CGI-Scripts auch in vielen anderen Sprachen geschrieben sein, jedoch werden wir, da es sich schließlich um ein Perl-Wikibook handelt, lediglich auf selbiges näher eingehen. Zwar gibt es mittlerweile mit PHP und Co. gute Alternativen zu CGI-Scripts, jedoch findet man im WWW immer noch zahlreiche Anwendungsmöglichkeiten. Ein Perl-Modul um das alles zu realisieren ist CGI[1].

Allerdings wurde dieses Modul ab der Perl-Version 5.22 aus dem Kern entfernt (es kann aber, wie jedes andere CPAN-Modul, zusätzlich installiert werden). Der Grund für diese Entscheidung ist, dass CGI.pm ist nicht mehr als gute Praxis für die Entwicklung von Web-Anwendungen - einschließlich schnellem Prototyping und kleinen Web-Skripten - betrachtet werden kann. Es gibt zahlreiche bessere und modernere Alternativen. Sie werden verglichen und dokumentiert in CGI::Alternatives[2].

Wie funktioniert CGI

Um zu verstehen, wie CGI funktioniert, muss man verstehen, wie Webserver mit Anfragen umgehen. Eine typische Anfrage an einen Webserver sieht in etwa so aus:

 GET /test.html HTTP/1.1
 Host: www.blubb.com

Hier wird der Webserver darum gebeten die Datei test.html anzufordern und dem Client zu präsentieren. Der Webserver antwortet darauf, je nachdem, ob die Seite eben existiert oder nicht, mit verschiedenen Codes. Wir nehmen jetzt an die Seite existiert:

 HTTP/1.1 200 OK
 Server: Apache/1.3.29 (Unix) PHP/4.3.4
 Content-Length: Größe von test.html in Byte
 Content-Language: de
 Content-Type: text/html
 Connection: close
 
 ... Inhalt von test.html ... 

Der Inhalt von test.html wird dann vom jeweiligen Browser in eine menschenlesbare Form gebracht und dargestellt.

Sollte der Webserver bemerken, dass es sich bei der angeforderten Ressource um ein CGI-Script handelt, was er daran merkt, dass sich das File im jeweiligen cgi-bin-Verzeichnis befindet, führt er das Script aus und gibt dessen Output direkt an den Browser weiter. Hier ein typischer Ablauf:

 GET /cgi-bin/test.cgi HTTP/1.1
 ...

In diesem Fall erkennt der Webserver das cgi-bin im Request. Viele Webspace-Anbieter verlangen, dass CGI-Scripts in eben diesem Verzeichnis gespeichert sind und verbieten die Ausführung von Scripts die nicht in diesem Verzeichnis liegen.

Einführendes Beispiel ohne CGI-Modul

Rein theoretisch ist es nicht notwendig, das CGI-Modul einzubinden. Man könnte es, wie in folgendem Beispiel zu sehen, auch ohne Einbindung des Moduls zum gewünschten Ergebnis kommen.

#!/usr/bin/perl
use strict;

print "Content-Type: text/html\n\n";
print "<html>\n";
print "<head><title>Testpage</title></head>\n";
print "<body>\n";
print "<h1>Test</h1>\n";
print "</body>\n";
print "</html>\n";


Nachdem man dieses Script ausführbar gemacht hat und es ins jeweilige cgi-bin-Verzeichnis kopiert hat, sollte man es via Browser ansteuern können und eine Überschrift namens "Test" sehen.


Was geschieht hier?


Der Webserver erkennt, dass es sich um ein CGI-Script handeln muss ( wegen Verzeichnis cgi-bin ) und führt es aus. Der Output wird direkt an den Browser weitergegeben. Die Anweisung print "Content-Type: text/html\n\n"; erklärt dem Browser worauf er sich einstellen kann, in diesem Fall also ein HTML-Dokument. Der Rest sollte eigentlich, so fern man ein wenig HTML-Erfahrung hat, selbsterklärend sein.

Einführendes Beispiel mit CGI-Modul

"Wozu brauche ich dieses Modul dann überhaupt?!" könnte der ein oder andere nun fragen. Nun, für manche Anwendungen scheint das CGI-Modul wirklich sinnlos zu sein, jedoch nur auf den ersten Blick. Denn manche Dinge sind mit dem CGI-Modul schlichtweg einfacher zu realisieren. Hier das vorherige Beispiel nochmals, jedoch diesmal mit Einbindung des CGI-Moduls:

#!/usr/bin/perl
use strict;
use CGI qw/:standard/;

print header();
print start_html(-title => 'Testpage');
print h1('Test');
print end_html();

Sieht doch gleich kompakter aus, oder nicht? Aber was passiert hier?

Zuerst wird dem Browser mittels header der Header gesendet. Dies ist im Grunde das selbe, wie im vorherigen Beispiel die print-Anweisung mit dem Content-Type. Danach wird mit start_html der HTML-Header erstellt. Das bedeutet, alle optionalen Anweisungen des <head>-Teils können hier hineingepackt werden. Mehr dazu später. Zuletzt schreibt start_html noch das <body>. Somit befinden wir uns ab jetzt im sichtbaren Teil des HTML-Dokuments. Die h1-Funktion gibt, wie erwartet, eine <h1>-Überschrift aus. Mit end_html wird das HTML-Dokument abgeschlossen, es entspricht also </html>.

Module

  1. CGI im CPAN: CGI
  2. http://search.cpan.org/~leejo/CGI-Alternatives-0.14/lib/CGI/Alternatives.pm

DBI: Datenbankzugriffe in Perl

Einleitung

Perl besitzt dank des DBI-Moduls[1] und diversen Datenbanktreibern (engl. database drivers, DBD) eine Schnittstelle, um mit verschiedenen Datenbanksystemen arbeiten zu können. Darunter fallen populäre Open-Source-Produkte wie MySQL und PostgreSQL sowie kommerzielle Riesen wie Oracle. Derzeit umfasst dieser Abschnitt die Möglichkeiten der Anbindung an MySQL, PostgreSQL und CSV-Dateien.

Zugriff auf MySQL mit DBI

Mit Perl und dem DBI-Modul ist es leicht, sich mit einer MySQL-Datenbank zu verbinden und Abfragen abzusetzen. Wenn das geeignete Perl-Modul für die Verbindung zu MySQL installiert ist ( DBD::mysql[2] ) und eine MySQL-Datenbank erreichbar ist, kann es auch schon losgehen. Elementare SQL-Kenntnisse sind dabei natürlich hilfreich. Weiterführende Erklärungen liefert die Dokumentation des Modules DBI.

Einfaches Beispiel

 1 #!/usr/bin/perl
 2 use strict;
 3 use warnings;
 4 use DBI;
 5 
 6 # Deklaration der noetigen Variablen fuer die Verbindung
 7 # Falls die Datenbank nicht lokal liegt, muss man zusaetzlich
 8 # die Variablen $db_host und/oder $db_port angeben
 9 # my $db_host = '127.0.0.1';
10 # my $db_port = 3306;
11 
12 my ($db_user, $db_name, $db_pass) = ('deinuser', 'deineDB', 'deinpass');
13 
14 # Verbindung zur DB herstellen
15 # alternativ ( wenn DB nicht lokal ):
16 # my $dbh = DBI->connect("DBI:mysql:database=$db_name;host=$db_host;port=$db_port", 
17 #                         "$db_user", "$db_pass");
18 # Man kann auch noch Fein-Tuning betreiben, z.B. mit dem RaiseError- oder dem AutoCommit-Switch.
19 # Naeheres dazu steht in der Dokumentation des Modules DBI.
20 my $dbh = DBI->connect("DBI:mysql:database=$db_name", $db_user, $db_pass);
21 
22 # Vorbereiten der SQL-Anweisung
23 
24 my $query_test = $dbh->prepare('SELECT * FROM deinetabelle');
25 
26 # Ausfuehren der Anweisung
27 
28 $query_test->execute() or die $query_test->err_str;
29 
30 # Hier koennte weitergehende Verarbeitung erfolgen, beispielsweise eine Auflistung aller Eintraege:
31 
32 while (my ($col_1, $col_2, $col_3) = $query_test->fetchrow_array() ) {
33     print "Spalte 1: $col_1 \n";
34     print "Spalte 2: $col_2 \n";
35     print "Spalte 3: $col_3 \n";
36 }
37 
38 # Nun erstellen wir doch noch gleich eine neue Tabelle
39 # Statt der Möglichkeit mittels vorherigem prepare() und execute(),
40 # benutzen wir hier die einfache Methode do()
41 
42 my $create_query = 'CREATE TABLE test_table';
43 
44 $dbh->do($create_query);
45 
46 # Nachdem alles erledigt ist, schließen wir die Datenbankverbindung
47 
48 $dbh->disconnect();

Die eigentliche Arbeit in diesem Script steckt in Zeile 31. Hier wird mittels der Funktion fetchrow_array jeweils eine Zeile aus der Datenbank gelesen und zurückgeliefert. Die ersten 3 Werte dieser Liste werden danach den Werten $col_1 bis $col_3 zugewiesen. Sobald fetchrow_array keine Zeile mehr zurückliefert, beendet sich die while-Schleife.

Erweitertes Beispiel mit Zugangsdaten in einem Modul

Im Sinne der Sicherheit, Portabilität und Faulheit ist es von Vorteil, die Zugangsdaten in einer externen Datei ( eventuell in Form eines Moduls ) zu halten und einfach in jedes Skript einzubinden. Wenn sich die Zugangsdaten ändern, bleibt damit der Verwaltungsaufwand gering. Ansonsten müssten die Zugangsdaten in jedem Script händisch angepasst werden. Außerdem ist in diesem Fall auch die Weitergabe des Quelltextes eher unbedenklich, da die brisante Information in einer separaten Datei steckt. Die Datei mit den Zugangsdaten sollte dann verständlicherweise nicht für jedermann lesbar sein.

Im folenden Beispiel werden die Zugangsdaten im Modul ZugangsDaten gehalten.

Die Datei mit den Zugangsdaten ( ZugangsDaten.pm ):

 1 #!/usr/bin/perl
 2 use strict;
 3 use warnings;
 4 use base 'Exporter';
 5 
 6 our @EXPORT_OK = qw($DB_USER $DB_PASSWD $DATABASE);
 7 
 8 package ZugangsDaten;
 9 
10 our $DB_USER   = 'youruser';
11 our $DB_PASSWD = 'yourpasswd';
12 our $DATABASE  = 'yourDB';
13 
14 1;

Die Datei ZugangsDaten.pm sollte nun mit sicheren Zugriffsrechten versehen werden. Nachdem das erledigt ist, kann man das erste Beispiel auch wie folgt formulieren:

 1 #!/usr/bin/perl
 2 use strict;
 3 use warnings;
 4 use DBI;
 5 use lib '.';
 6 use ZugangsDaten qw($DB_USER $DB_PASSWD $DATABASE);
 7 
 8 # Verbindung zur DB herstellen
 9 
10 my $dbh = DBI->connect("DBI:mysql:database=$DATABASE", $DB_USER, $DB_PASSWD);
11 
12 # Vorbereiten des SQL-Statements
13 
14 my $query_test = $dbh->prepare('SELECT * FROM deinetabelle');
15 
16 # ...
17 # ... alles andere bleibt gleich
18 # ...


Erklärung

In Zeile 5 wird Perl angewiesen das aktuelle Verzeichnis in den Suchpfad @INC aufzunehmen. Dies ist notwendig, damit die Datei ZugangsDaten.pm, wie in Zeile 6 gefordert, gefunden wird. Durch die package-Anweisung im Modul befinden sich die Variablen im Namensraum ZugangsDaten. Zur Vereinfachung exportiert das Modul Exporter die relevanten Variablen in den aktuellen Namensraum. Alternativ könnten die Variablen auch mit ihren qualifizieren Name, wie z.B $ZugangsDaten::DB_USER, angesprochen werden.

DBI-Zugriff auf andere Datenbanksysteme

Im wesentlichen können hier die Erkenntnisse des letzten Kapitels übernommen werden. Den größten Unterschied stellt lediglich die connect-Anweisung dar, die für jedes DBMS etwas anders ausschaut. Des weiteren sollten, um die folgenden Beispiele ausführen zu können, die Module DBD::Pg[3] für PostgreSQL sowie DBD::CSV[4] für CSV installiert sein. Beide Module sind im CPAN zu finden.

PostgreSQL

my $dbh = DBI->connect("DBI:Pg:dbname=$db_name", $db_user, $db_pass);

Ein CSV-Verzeichnis

CSV steht für "Comma-separated Values", und bezeichnet keine Datenbank im eigentlichen Sinne, sondern einen Dateityp, eigentlich reine Textdateien im ASCII-Format, die von jedem Texteditor gelesen und bearbeitet werden können. Damit hat der Programmierer die Möglichkeit, SQL zu nutzen, ohne ein DBMS installieren zu müssen. Vorteilhaft, wenn man sparsam mit den Ressourcen umgehen muß.

Als Datenbank verwendet man ein Verzeichnis, und jede CSV-Datei steht für eine Tabelle. Benutzername und Passwort entfallen.

my $dbh = DBI->connect('DBI:CSV:f_dir=/pfad/zu/deinem/csvverzeichnis');

#Oder bei Windows
my $dbh = DBI->connect('DBI:CSV:f_dir=c:\pfad\zu\deinem\csvverzeichnis');

SDBM

SDBM (Standard-Perl-Quelldistribution) ist eine sehr einfache Datenbank, die häufig bei einer gewöhnlichen Linux-Distribution standardmäßig installiert wird. Es werden zwei Dateien erzeugt. Eine mit der Endung .dir und eine .pag, wobei letztere die Daten beinhaltet. Für SDBM-Datenbanken gibt es den DBI-Treiber DDBD::DBM[5]. Man kann aber auch das Modul SDBM_File verwenden.

Hier ein erklärendes Beispiel eingebettet in eine Klasse:

package TemperaturDB;
    
use Fcntl;                                    # O_RDWR, O_CREAT, etc.
use SDBM_File;
    
sub new                                       # Konstruktor
{
    my $this  = shift;
    my $class = ref($this) || $this;
    
    my $self  = {
        temperatur => {},                     # Temperaturwerte
    };
    
    bless $self, $class;                      # Objekt erzeugen
   
    tie(%{$self->{temperatur}}, 'SDBM_File','temperatur.db', O_RDWR|O_CREAT, 0666);
    
    return $self;
}

Der Konstruktor verbindet das Hash %{$self->{temperatur}} mit der Datenbank (temperatur.db). Im aktuellen Verzeichnis werden die Dateien temperatur.db.dir und temperatur.dp.pag angelegt bzw. benutzt.

sub write_db
{
    my $self  = shift;
    my $key   = shift;                         # Datenschluessel
    my $value = shift;                         # Datenwert

    $self->{temperatur}->{$key} = $value;

    return 1;
}

Die Funktion write_db schreibt Daten in die Datenbank.

sub read_db
{
    my $self = shift;
    my $key  = shift;                         # Datenschluessel

    return $self->{temperatur}->{$key};
}

Die Funktion read_db liest bestimmte Daten der Datenbank aus.

sub DESTROY
{
    my $self = shift;

    untie %{$self->{temperatur}};
}
1;                                            # Returnwert für Package

Der Destruktor löst die Verbindung wieder auf und schließt somit die Datenbank wieder.


Das folgende Beispiel zeigt, wie diese Klasse benutzt werden kann:

#!/usr/bin/perl
use strict;
use warnings;

use TemperaturDB;
  
my $db = TemperaturDB->new();                      # Konstruktor wird aufgerufen
$db->write_db( 'InnenTemperatur' =>  21.0);        # Daten schreiben
print 'Innentemperatur: ', $db->read_db('InnenTemperatur'), "\n"; # Daten lesen

Module

  1. CPAN: DBI
  2. CPAN: DBD::mysql
  3. CPAN: DBD::Pg
  4. CPAN: DBD::CSV
  5. CPAN: DBD::DBM


Beispiele

Fallunterscheidung

Ein Beispiel für eine if/elseif/else-Struktur

#!/usr/bin/perl -w
# if/elsif/else
# 20041110
  
if (1233 > 2333) {
    print "Ergebnis 1\n";
}
elsif (3333 > 4444) {
    print "Ergebnis 2\n";
} 
else {
    print "Ergebnis 3\n";
}
  
# ergibt: Ergebnis 3
# das selbe ohne if/elsif/else (TIMTOWTDI-Prinzip)
  
print "Ergebnis ", 1233 > 2333 ? 1 : 3333 > 4444 ? 2 : 3, "\n";

Ein Beispiel für den Vergleich von Strings

#!/usr/bin/perl -w
# Stringvergleich eq, ne (equal, not equal)
  
if ("huhu" eq "huhu") {
    print "beide Zeichenketten gleich";
}

if ("wiki" ne "books") {
    print "strings sind unterschiedlich";
}

Vergleiche mit String-Variablen

#!/usr/bin/perl
#@potbot
#Vergleich mit Variablen/String (If/else)
#Usereingabe mit -> String-Variable

print"Wie heißt der Erfinder dieser schönen Sprache?\n";

$userinput=<STDIN>;                              # Variable in der die Usereingabe gespeichert wird. <STDIN>=Standard-Input.
$var1='Larry Wall';                              # Vergleichsvariable mit dem String-Wert 'Larry Wall'.
chomp($userinput);                               # Chomp entfernt den Zeilenumbruch von der Usereingabe. Wichtig!
                                                 
if ($userinput eq $var1){                        # String-Vergleiche immer mit 'eq'(equal) oder 'ne'(not equal).
print"Richtige Antwort! :D\n";                  
}
else {                                           
print"Hmm, wer hat denn hier nicht aufgepasst?! ;D\n";
}

#--~~~~

Ein weiteres Beispiel

#!/usr/bin/perl -w
# 20041110
  
print "1+1 = 4\n" if 1+1 == 2;

something else

#!/usr/bin/perl -w
print "\aAlarm\n";                              # \a gibt einen Piepton aus, es folgt die Zeichenkette 'Alarm'
                                                # und \n gibt eine neue Zeile aus;
print `hostname`;                               # fuehrt das Kommando "hostname" in einer Shell aus und liest
                                                # die Standardausgabe der Shell und zeigt diese als Resultat
                                                # an. "hostname" ist also kein Perl-Befehl!;

$var0 = "0123456789";
print substr($var0, 3, 5);                      # gibt '34567' aus; substr holt aus $var0 von Zeichen nr.3 die 
                                                # darauf folgenden 5 Zeichen und gibt sie aus ...;

Dateihandling

Ausgabe des Inhaltes von $text in die Datei test.txt

 #!/usr/bin/perl
 print "Wie heißt Du? ";
 #aus der Standardeingabe lesen
 $text = <STDIN>;
 #letztes Zeichen von $text (\n) entfernen
 chomp($text);
 open(file, ">test.txt") or die "Fehler beim Öffnen der Datei: $!\n";
 #$text in file schreiben
 print file $text;
 close (file) or die "Fehler beim Schließen von 'test.txt': $! \n";

Umwandlung in HTML

Funktion zur Umwandlung von Umlauten in deren HTML-Äquivalente. Alternativ können diese mit dem Zusatzparameter '2' auch in der Doppellautschreibweise dargestellt werden. Die ganze Funktion kann in eine Bibliotheks-Datei im cgi-bin-Verzeichnis ausgelagert werden, um dann bei Bedarf von allen CGI-Perl-Dateien mit "require" eingebunden zu werden.

sub umlautwechseln {
    my $return = $_[0];          # erster Parameter
    my $matchcode = $_[1];       # zweiter Parameter
    if(!defined($matchcode)) {
        $matchcode = 1;
    }

    my @vorlage = (
        ['ä',      'ö',      'ü',      'Ä',      'Ö',      'Ü',      'ß'],
  	['&auml;', '&ouml;', '&uuml;', '&Auml;', '&Ouml;', '&Uuml;', '&szlig;'],
  	['ae',     'oe',     'ue',     'Ae',     'Oe',     'Ue',     'ss']
    );

    my $vorlage = 0;
    for (my $i=0; $i<=6; $i++) {                           # alternativ: for ( 0 .. 6 )
        while ( index($return, $vorlage[0][$i], 0) > -1 ) {
            substr ($return, index($return, $vorlage[0][$i], 0), 1) = $vorlage[$matchcode][$i];
        }
    }

    return $return;
}

1;

Das selbe Beispiel könnte ebenfalls mit Regular-Expressions gelöst werden, wie man im folgenden Beispiel sehen kann:

#!/usr/bin/perl
use strict;
use warnings;

sub umlautwechseln {
    my $messystring = shift;
    my $conversion = shift || "1";

    my @vorlage = (
        [   'ä',   'ö',      'ü',      'Ä',      'Ö',     'Ü',      'ß'],
        ['&auml;', '&ouml;', '&uuml;', '&Auml;', '&Ouml;','&Uuml;', '&szlig;'],
        [   'ae',  'oe',     'ue',     'Ae',     'Oe',    'Ue',     'ss']
    );

    for (0 .. 6) {
        $messystring =~ s/$vorlage[0][$_]/$vorlage[$conversion][$_]/g;
    }

    return $messystring;
}

Erläuterung der Funktion:

Diese Funktion erwartet 2 Parameter, wobei der zweite Parameter optional ist ( $conversion ). Falls der zweite Parameter nicht angegeben wird, wird der Wert "1" angenommen. Der erste Parameter ist der Skalar mit den Sonderzeichen.

In Zeile 16 erfolgt die eigentliche Arbeit. $messystring wird mittels RegEx untersucht und entsprechende Treffer werden ersetzt.

Erzeugung von SQL-Code

Dieses Script kann genutzt werden für die Beispieldatenbank der Einführung in SQL. Es erzeugt etwas mehr als 100.000 SQL-Anweisungen für MySQL, die mit einer Kanalumleitung in die Beispieldatenbank eingespielt werden können, und dort jeweils einen Datensatz erzeugen.

Hinweis: Die Tabellen wurden inzwischen geändert, siehe Anmerkungen zur Beispieldatenbank. Bitte beachten Sie, dass im Laufe der Arbeit mit Änderung der Datenbankstruktur weitere Spalten angelegt werden und danach auch dafür Werte benötigt werden.

Glasbutton Warnung.svg

Für die Beispieldatenbank fehlen Datensätze für die Tabellen Fahrzeug und Versicherungsnehmer. In der jetzigen Version des folgenden Skripts werden die Bedingungen der Fremdschlüssel (ForeignKeys) verletzt.

Für Perl-Neulinge von Interesse sind vermutlich eher

  • die Verwendung der ForEach-Schleife,
  • die alternative Textausgabe, die besonders für längere Texte geeignet ist,
  • der alternative Zugriff auf die Datenbank, der ohne das DBI-Modul auskommt.
 #!/usr/bin/perl

 use strict;

 my @namen=("Meyer", "Müller", "Schulze", "Schneider", "Schubert", "Lehmann", 
  "Bischof", "Kretschmer", "Kirchhoff", "Schmitz", "Arndt");
 my @vornamen=("Anton", "Berta", "Christoph", "Dieter", "Emil", "Fritz", "Gustav", 
  "Harald", "Ida", "Joachim", "Kunibert", "Leopold", "Martin", "Norbert", "Otto", 
  "Peter", "Quentin", "Richard", "Siegfried", "Theodor", "Ulf", "Volker", "Walter", 
  "Xaver", "Yvonne", "Zacharias");
 my @orte=("Essen", "Dortmund", "Bochum", "Mülheim", "Duisburg", "Bottrop", 
  "Oberhausen", "Herne", "Witten", "Recklinghausen", "Gelsenkirchen", 
  "Castrop-Rauxel", "Hamm", "Unna", "Herten", "Gladbeck");
 my $orte="";
 my @strassen=("Goethestr.", "Schillerstr.", "Lessingstr.", "Badstr.", "Turmstr.", 
  "Chausseestr.", "Elisenstr.", "Poststr.", "Hafenstr.", "Seestr.", "Neue Str.", 
  "Münchener Str.", "Wiener Str.", "Berliner Str.", "Museumsstr.", "Theaterstr.", 
  "Opernplatz", "Rathausplatz", "Bahnhofstr.", "Hauptstr.", "Parkstr.", 
  "Schlossallee");
 my @gesellschaften=("Zweite allgemeine Verabsicherung", "Sofortix 
  Unfallversicherung", "Buvaria Autofutsch", "Provinziell", "Vesta Blanca");
 my @beschreibungen=("Standardbeschreibung Nr 502", "08/15", "Blablabla", 
  "Der andere war schuld!", "Die Ampel war schuld!", "Die Sonne war schuld!", 
  "Die Welt ist schlecht!!");
 my $beschreibungen="";
 my $gesellschaften=0;
 my $gebdat="";
 my $fdat="";
 my $hnr=0;
 my $eigen="";

 foreach my $ort (@orte) {
   my $gplz=int(rand(90000))+10000;
   foreach my $strasse (@strassen) {
     my $plz=$gplz+int(rand(20));
     foreach my $name (@namen) {
       foreach my $vorname(@vornamen) {
         $gebdat=dating(80, 1907);
         $fdat=dating(80, 1927);
         $hnr=int(rand(100))+1;
         if(rand(2)>1) {$eigen="TRUE";} else {$eigen="FALSE";}
         my $vers=int(rand(5));

 print <<OUT1
 insert into VERSICHERUNGSNEHMER(NAME, VORNAME, GEBURTSDATUM, 
 FUEHRERSCHEIN, ORT, PLZ, STRASSE, HAUSNUMMER, 
 EIGENER_KUNDE, VERSICHERUNGSGESELLSCHAFT_ID) values ("$name", 
 "$vorname", "$gebdat", "$fdat", "$ort", "$plz", "$strasse", "$hnr", "$eigen", 
 "$vers");
 OUT1
 }}}}

 for(my $a=0; $a<=500; $a++)
 {
   my $udat=dating(3, 2004);
   my $ort=$orte[int(rand(16))];
   my $beschreibung=$beschreibungen[int(rand(7))];
   my $shoehe=int(rand(20000000))/100;
   my $verletzte;
   if(rand(2)>1) {$verletzte="TRUE";} else {$verletzte="FALSE";}
   my $mitarbeiter=int(rand(10))+1;
 print <<OUT2
 insert into SCHADENSFALL(DATUM, ORT, BESCHREIBUNG, 
 SCHADENSHOEHE, VERLETZTE, MITARBEITER_ID) values 
 ("$udat", "$ort", "$beschreibung", $shoehe, "$verletzte", $mitarbeiter);
 OUT2
 }

 for(my $a=1; $a<=500; $a++)
 {
   my $vne=int(rand(100000))+1;
 print <<OUT3
 insert into ZUORDNUNG_SF_FZ(SCHADENSFALL_ID, FAHRZEUG_ID) values 
 ($a, $vne);
 OUT3
 }

 sub dating
 {
   my $range=$_[0];
   my $radix=$_[1];
   my $y=int(rand($range))+$radix;
   my $m=int(rand(12))+1;
   my $d=int(rand(28))+1;
   my $return=$y . "-" . $m . "-" . $d;
   return $return;
 }


Anhänge

Funktionsreferenz

Arrayfunktionen

push, unshift

Mit push kann man einen Wert oder eine Liste von Werten hinten an einen Array anhängen, mit unshift kann man Selbiges vorne anhängen.

my @array=("Berta", "Caesar", "Dora");

push (@array, "Emil");
unshift (@array, "Anton");

print "@array\n";
 Ausgabe:
 $ perl pushunshifttest.pl 
 Anton Berta Caesar Dora Emil
 $


pop, shift

pop entfernt den letzten Wert aus dem Array, shift den ersten.

my @array=("Anton", "Berta", "Caesar", "Dora", "Emil");

pop (@array);
print "@array\n";

shift (@array);
print "@array\n";
 Ausgabe:
 $ perl popshifttest.pl 
 Anton Berta Caesar Dora
 Berta Caesar Dora
 $

Praxisbeispiel
Mit pop und shift entfernt man nicht nur das erste Element aus einem Array, sondern gibt es auch zurück. Dies kann man sich mit Hilfe der Spezialvariablen @_ zu Nutze machen:

sub max {
    # Es wird standardmäßig @_ verwendet.
    my $a = shift; # a enthält nach Ausführung den ersten Parameter
    my $b = shift; # b enthält den zweiten Parameter
    if ($a > $b) {
        return $a;
    } else {
        return $b;
    }
}

split

Mit split kann man mit Hilfe eines Trennzeichens einen String aufteilen und die entstehenden Einzelwerte in einem Array festhalten.

my @array=split(",", "Anton,Berta,Caesar,Dora,Emil");
print "@array\n";
 Ausgabe:
 $ perl splittest.pl 
 Anton Berta Caesar Dora Emil
 $

Für das von split verwendete Trennzeichen kann jeder beliebige reguläre Ausdruck verwendet werden. Es kann außerdem mit einem dritten Parameter die Anzahl der Ergebnisse beschränkt werden. Da leere Felder ohne den dritten Parameter nicht im Array auftauchen, ist er außerdem notwendig, um eine konstante Anzahl von Feldern im Ergebnis zu erhalten. Ein negativer Wert an dieser Stelle wirkt wie ein beliebig großer Grenzwert.

   my $data=<<__CSV__;
   eins,zwei,drei
   1,,
__CSV__

   foreach my $line (split /\n/,$data) {
       print scalar @{[split /,/,$line,2]}," ";        # 2 und 2
       print scalar @{[split /,/,$line]}," ";          # 3 und 1
       print scalar @{[split /,/,$line,-1]},"\n";      # 3 und 3
   }

join

Mit join kann man umgekehrt einen Array in einen String umwandeln, und zwischen jeden Einzelwert ein Trennzeichen schieben:

my @array=("Anton", "Berta", "Caesar", "Dora", "Emil");
my $string = join(", ", @array);

print $string ."\n";
 Ausgabe:
 $ perl jointest.pl 
 Anton, Berta, Caesar, Dora, Emil
 $


sort

Sort sortiert den Inhalt eines Arrays nach ASCII-Werten.

my @array=sort ("Dora", "Berta", "Emil", "Caesar", "Anton");

print "@array\n";
 Ausgabe:
 $ perl sorttest.pl 
 Anton Berta Caesar Dora Emil
 $

Hash-Funktionen

keys, values

Die Funktion keys gibt jeweils eine Liste der Identifier eines Hashes zurück, die Funktion values liefert jeweils eine Liste mit den Werten.

#!/usr/bin/perl
use strict;
use warnings;

my %hash = ( '1'  => "eins",
             '2'  => "zwei",
             '3'  => "drei",
             '4'  => "vier"
);

for (sort keys %hash) {
    print "$_\n";
}
for (sort values %hash) {
    print "$_\n";
}
 Ausgabe:
 $ perl hash.pl 
 1
 2
 3
 4
 drei
 eins
 vier
 zwei
 $

each

Die Funktion each gibt bei jedem Durchlauf das nächste Schlüssel-Wert-Paar eines Hashes aus. In einer Schleife kann man damit den gesamten Hash durchgehen.

#!/usr/bin/perl
use strict;
use warnings;

my %hash = ( '1'  => "eins",
             '2'  => "zwei",
             '3'  => "drei",
             '4'  => "vier"
);

for (my ($key, $value) = each %hash) {
    print "$key -> $value\n";
}
 Ausgabe:
 $ perl hash2.pl 
 1 -> eins
 2 -> zwei
 3 -> drei
 4 -> vier
 $


Stringfunktionen

substr

substr(ZEICHENKETTE, STARTBUCHSTABE, ANZAHLZEICHEN) erlaubt es, gezielt Bestandteile einer Zeichenkette (String) zu ermitteln. Dabei ist zu beachten, dass der 1. Buchstabe für Perl der 0. Buchstabe ist.


#!/usr/bin/perl

use strict;
use warnings;

my $langeswort="Donaudampfschiffdudelsackpfeifer";
my $fluss=substr($langeswort, 0, 5);
my $aggregatszustand=substr($langeswort, 5, 5);
my $transportmittel=substr($langeswort, 10, 6);
my $instrument=substr($langeswort, 16, 9);
my $rauchgeraetnutzer=substr($langeswort, 25, 7);

print "$fluss\n$aggregatszustand\n$transportmittel\n$instrument\n$rauchgeraetnutzer\n";

In Perl ist es mit substr außerdem möglich, schreibend auf die Zeichenkette zuzugreifen!!

...
substr($langeswort, 5, 5)="segel";
print "$langeswort\n";
 Ausgabe:
 $ perl substrtest.pl 
 Donau
 dampf
 schiff
 dudelsack
 pfeifer
 Donausegelschiffdudelsackpfeifer
 $

index, rindex

index(DURCHSUCHTE_ZEICHENKETTE, SUCHZEICHENKETTE, STARTPOSITION) zeigt die Position der Suchzeichenkette innerhalb der durchsuchten Zeichenkette an. Dabei beginnt index seine Suche an der Stelle der Startposition, die nicht zwingend vorgegeben werden muß. Wird keine Startposition angegeben, fängt index praktischerweise an der Stelle 0, also beim ersten Zeichen mit seiner Suche an. Wird index nicht fündig, gibt es den Rückgabewert -1 aus. index durchsucht die Zeichenkette von links nach rechts, rindex dagegen von rechts nach links.

#!/usr/bin/perl
 
use strict;
use warnings;
 
my $durchsuchtezeichenkette="Donaudampfschiffdudelsackpfeifer";
 
my $suchzeichenkette="Donau";
my $ergebnis=index($durchsuchtezeichenkette, $suchzeichenkette);
print "$ergebnis\n";
 
$suchzeichenkette="Elbe";
$ergebnis=index($durchsuchtezeichenkette, $suchzeichenkette);
print "$ergebnis\n";
 
$suchzeichenkette="Donau";
$ergebnis=index($durchsuchtezeichenkette, $suchzeichenkette, 5);
print "$ergebnis\n";
 
$suchzeichenkette="schiff";
$ergebnis=index($durchsuchtezeichenkette, $suchzeichenkette, 5);
print "$ergebnis\n";
 Ausgabe:
 $ perl indextest.pl 
 0
 -1
 -1
 10
 $

chop und chomp

split und join

split und join

quotemeta

quotemeta(ZEICHENKETTE)

Der Rückgabewert ist eine Zeichenkette, wo allen Zeichen, welche in einem regulären Ausdruck eine besondere Bedeutung haben, ein umgekehrter Schrägstrich (backslash) vorangestellt ist. Diese Funktion sollte immer dann verwendet werden, wenn nach einer nicht vorherbestimmten Zeichenfolge gesucht werden soll.

#!/usr/bin/perl
 
use strict;
use warnings;
 
open(FH,"<$0") or die "Kann den eigenen Programmcode nicht laden!";
my $text = join('',<FH>);
close(FH);

print "Bitte ein paar Zeichen eingeben:";
my $suche = <STDIN>;
chomp($suche);
$suche = quotemeta($suche);

print(($text =~ /$suche/ ? "gefunden" : "nicht da"),"\n");

mathematische Funktionen

abs

print abs(-3.42), "\n";

Die Funktion abs liefert den Absolutwert (= vorzeichenloser Wert) des übergebenen Arguments zurück.

 Ausgabe:
 $ perl abs.pl
 3.42


sonstige Funktionen

bless

bless bindet eine Referenz an eine Klasse. Sehr praktisch bei der objektorientierten Programmierung.

eval

open

Die open-Funktion hat in Perl zweierlei Bedeutung. Zum Einen benötigt man sie für das Dateihandling, zum Anderen kann man damit Systembefehle (Pipes) abschicken und deren Ergebnis auswerten.

#!/usr/bin/perl
# testlogfileanalyzer.pl

use strict;
use warnings;

my @t= split(" ", localtime());
my $heute=$t[1] ." ". $t[2] . "\n";

open(LOGMESSAGES, "grep $heute /var/log/* |") or die "Konnte grep-Befehl nicht ausführen: $!\n";
while(<LOGMESSAGES>)
{
  #Irgendeine Auswertungsfunktion
  ...
}
close(LOGMESSAGES) or  warn "Konnte grep-Befehl nicht abschließen: $?\n";

sub

sub wird naturgemäß in erster Linie zur Erzeugung von Subroutinen verwendet.

Ein nettes kleines Feature, das in Perl zur Verfügung steht, ist die Implementierung von ad-hoc-Subroutinen, die direkt an Ort und Stelle eingebaut werden, und nicht im Quelltext separiert werden. Das sorgt häufig für Unübersichtlichkeit und lohnt sich lediglich wenn mit Objekten, die eine Subroutine verlangen, gearbeitet wird, obwohl nur eine Kleinigkeit abgearbeitet werden muß. Sehr häufig kommt man bei der GUI-Programmierung in eine solche Situation.


use

use dient zur Implementation von externen Modulen in den Quellcode. Eine besondere Bedeutung kommt hierbei den Pragmas zu.


Nützliche Module

Vorbemerkung

In diesem Abschnitt werden nützliche Module vorgestellt, die Programmieraufgaben erheblich erleichtern.

Term::ANSIColor

Dieses Modul ermöglicht die Ausgabe auf der Kommandozeile einzufärben, um so die Übersichtlichkeit der Ausgabe zu steigern. Ein Programmbeispiel:

#!/usr/bin/perl -w
# Programm zur Demonstration der eingefärbten Kommandozeilenausgabe.

use Term::ANSIColor;

print colored("Hallo Welt \n",'Bold Blue');

Das Programm gibt Hallo Welt in einem satten Blau aus. Die Farbgebung ist sehr assoziativ, so würde zum Beispiel 'Yellow on_magenta' ebenfalls als Farbgebung funktionieren. Weitere Informationen stehen in der Anleitung.

perldoc Term::ANSIColor

Das Modul sollte nur verwendet werden, wenn eine unterschiedliche Farbgebung sinnvoll ist. Auf diese Weise werden Netzhautschäden beim Benutzer des Programms vermieden, was diesen sicherlich freut.

Data::Dumper

Wer kennt das nicht, man hat komplizierte Datenstrukturen und irgend etwas stimmt damit nicht. Wenn man jetzt nur die Möglichkeit hätte, diese Struktur auszugeben. Ein 'print $hash' liefert leider nur so etwas unverständliches wie 'HASH(0x814cc20)'.

Hier kann das Modul Data::Dumper helfen. Es importiert automatisch eine Funktion Dumper, die beliebige skalare Werte ausgeben kann (auch mehrere davon) und sogar mit Zyklen in der Datenstruktur zurechtkommt. Dazu ist die Ausgabe sehr gut lesbar. Hier ein Beispiel mit einer einfacheren und einer komplizierten Struktur:

use Data::Dumper;

my $simple = { a => 1 };

my $complicated = [ sub { ucfirst(shift) }, $simple ];
                    
push @$complicated, $complicated;

print Dumper($simple, $complicated);

Die erste Variable ($simple) ist einfach nur eine Hashreferenz, die zweite Variable ($complicated) arbeitet mit Codereferenzen und beinhaltet einen Zyklus. Bei der Ausgabe benennt Dumper die Variablen mit einem automatisch generierten Wert und benutzt diesen, um Zyklen und Verweise auf bereits dargestellte Inhalte zu verdeutlichen. Hier die Ausgabe des obigen Programms:

$VAR1 = {
          'a' => 1
        };
$VAR2 = [
          sub { "DUMMY" },
          $VAR1,
          $VAR2
        ];

Natürlich kann Dumper den Variablen noch vom Nutzer vorgegebene Namen geben oder die Rekursivtiefe der Darstellung begrenzen, diese und noch viele anderen Informationen sind in der Manualpage zu finden, einfach:

perldoc Data::Dumper

aufrufen.

Für mich ist Data::Dumper ein unentbehrliches Werkzeug und ein 'die Dumper($var)' ist ein schnelles Mittel um Probleme mit den Datenstrukturen zu finden.

File::Slurp

Dieses Modul beinhaltet Funktionen um eine Datei in einem Rutsch einzulesen oder zu schreiben. Es ist entstanden, weil diese Funktionen an unzähligen Stellen in Perlprogrammen und -modulen vorkommen. Außerdem ist die slurp-Funktion Bestandteil des kommenden Perl6, so daß man seinen Code schon für diese kommende Version vorbereiten kann.

Ein kleines Beispielprogramm das einen Textdatei neu formatiert. Warnung: nicht zur Verwendung mit wichtigen Textdateien vorgesehen!

     ; use strict; use warnings; use utf8
     
     ; use Text::Wrap  qw(wrap)
     ; use File::Slurp qw(slurp write_file)
     ; use IO::File
     
     ; my $x=@ARGV
     ; my $columns=72;
     
     ; if($x==2)
         { $columns = shift @ARGV }
       elsif($x==0)
         { print STDERR "$0 [columns] file\n"
         ; exit 1
         }
         
     ; my $filename=shift @ARGV
     ; my @file
       
     ; { # Read in
       ; my $in=new IO::File "<$filename" or die "$filename is unreadable\n"
       ; @file=slurp($in)
       }
     
     ; { # write out
       ; my $out=new IO::File ">$filename" or die "$filename is unwritable\n"
       ; $Text::Wrap::columns=$columns
       ; write_file($out, wrap('','',@file))
       }

Module::CoreList

Mit dem Befehl corelist ModulName kann man abfragen ob und ab wann das Modul ModulName zur Standardinstallation von Perl gehört.

Module::Starter

Liefert ein Gerüst für eigene Module.

Task::Kensho

Liste von Modulen, die von der Enlightened Perl Organization empfohlen werden.

WWW::Mechanize

Automatische Verarbeitung von Webseiten.

Moose

Vernünftige Objektorientierung.

Getopt::Long

Verarbeitung von Kommandozeilenparameter


Schnellreferenz

Funktionsübersicht

Hier befindet sich eine alphabetische Auflistung aller Perl-Standardfunktionen. Dieser Abschnitt soll als schneller Überblick dienen.

A


abs


B

bless

C

chomp chop

D

E

each eval

F

G

H

I

index

J

join

K

keys Kommandozeilenparameter

L

M

N

O

P

pop push

Q

R

rindex

S

shift sort split sub substr

T

U

unshift

V

values

W

X

Y

Z

Webseiten und mehr

Webseiten und mehr

im web unter:

  • www.perl.org die zentrale Netzseite zu Perl (enthält schon alle Links, die man braucht);
  • www.cpan.org zentrales Download-Register für Perl und Perl-Module, inklusive praktischer Suchfunktion;
  • ActivePerl ist die unter Windows am weitesten verbreitete Perl-Distribution;
  • perldoc.perl.org offizielle Perl-Dokumentation und [1] Perl-Bücher online;
  • [2] Perl-Nachrichten und [3] aktuelle Berichte;
  • deutschsprachige Perl-Nachrichten
  • Perl Monks großes Portal für Perl-Benutzer: Hilfe, Diskussionen, Anleitungen (auf englisch);
  • Perl Mongers weltweites Netzwerk lokaler Benutzergruppen, [4] auch in Deutschland;
  • [5] Portal deutscher Perl-Gemeindschaft mit Forum, Wiki, Links, etc.;
  • [6] witzige und intelligente Schriften, nicht nur über Perl;
  • [7] Kolumnen und Programmierbeispiele vom Perlmeister;
  • [8] Kolumnen von Merlin, Altmeister der Perl-Magie;
  • [9] Perl-Seiten - eine Einführung zu Perl
  • [10] Portal mit Forum, Downloads, Links, etc.;
  • ...

Hilfreiche Befehle

  • man perl
  • perldoc xy
  • perldoc -f <funktionsname> (z.B. perldoc -f print) gibt uns eine praktische Anleitung zu der Perlfunktion
  • man perlfunc ( Übersicht aller wichtigen Perlfunktionen )
  • ...


Buchtipps

zum Einstieg:

automatisiertes Testen:

  • Ian Langworth, chromatic: Perl Testing - A Developer's Notebook, O'Reilly Media, Inc., 2005, ISBN 0-596-10092-2

mit Praxisbeispielen:

zur Weiterbildung:


Glossar

Vorbemerkung

Das hier soll als kleines Nachschlagewerk dienen.


abgeleitete Klasse
Eine Klasse, die ihre Methoden über eine allgemeinere Klasse, eine so genannte Basisklasse, beschreibt. Beachten Sie, dass Klassen nicht ausschließlich in Basisklassen oder abgeleitete Klassen unterteilt werden; eine Klasse kann gleichzeitig sowohl eine abgeleitete Klasse als auch eine Basisklasse darstellen.
abschneiden
(engl. »truncate«) Das Entfernen eines vorhandenen Inhalts aus einer Datei. Das kann automatisch beim Öffnen einer Datei mit Schreibrechten oder explizit über die truncate-Funktion erfolgen.
Accessor-Methode
Eine Methode, die zur indirekten Inspektion bzw. Aktualisierung des Zustandes eines Objekts (seiner Instanzvariablen) verwendet wird.
Adressoperator
Einige Sprachen arbeiten direkt mit den Speicheradressen von Werten, was aber leicht zu einem Spiel mit dem Feuer werden kann. Perl stellt Ihnen einige Funktionen, die Ihnen das Speichermanagement abnehmen. Bei Perl kommt der Backslash-Operator einem Adressoperator am nächsten. Er versorgt sie aber mit einer harten Referenz , was wesentlich sicherer ist, als eine Speicheradresse.
aktuelles Paket
Das Paket, in dem die aktuelle Anweisung kompiliert wird. Gehen Sie in Ihrem Programm zurück, bis Sie eine Paketdeklaration im gleichen lexikalischen Geltungsbereich oder in allen umschließenden lexikalischen Geltungsbereichen finden. Das ist der Name Ihres aktuellen Paketes.
Algorithmus
Eine genau definierte Folge von Schritten, die so umfassend erläutert sind, dass sie ein Computer ausführen kann.
Alias
Ein Spitzname für irgendetwas, der sich in allen Fällen so verhält, als würden Sie den ursprünglichen Namen verwenden und nicht dessen Spitznamen. Temporäre Aliase werden implizit in der Schleifenvariable für „foreach-Schleifen“, bei der „$Variable“ für die „map-“ oder „grep-Operatoren“, für „$a“ und „$b“ während der sort-Vergleichsfunktionen und bei jedem Element von „@_“ für die tatsächlichen Argumente eines Subroutinen-Aufrufs erzeugt. Permanente Aliase werden in Paketen explizit erzeugt, indem man Symbole importiert oder an Typeglobs zuweist. Lexikalisch beschränkte Aliase für Paketvariablen werden explizit durch die our-Deklaration erzeugt.
Alternativen
Eine Liste mit mehreren Wahlmöglichkeiten, unter denen Sie sich eine aussuchen können. Alternativen werden in regulären Ausdrücken durch den vertikalen Strich (|) voneinander getrennt. Alternativen in normalen Perlausdrücken werden von zwei vertikalen Strichen (||) voneinander getrennt. Logische Alternativen in Booleschen werden durch (||) oder durch „or“ getrennt.
anonym
Wird verwendet um einen Referenten zu beschreiben, der nicht direkt durch eine benannte Variable zu erreichen ist. Ein solcher Referent muss indirekt über mindestens eine harte Referenz zugänglich sein. Wenn die letzte harte Referenz verschwindet, wird der anonyme Referent gnadenlos entfernt.
Anweisung
Ein Befehl an einem Computer, der angibt, was als nächstes zu geschehen hat.Ist nicht mit der Deklaration zu verwechseln, die ihren Computer nicht anweist, etwas zu tun, sondern nur, etwas zu lernen.
Anweisungsmodifizierer
Eine Bedingungsanweisung die hinter einer Schleife steht, und nicht davor.
Arbeitsverzeichnis
Ihr aktuelles Verzeichnis, von dem ausgehend relative Pfadnamen vom Betriebssystem interpretiert werden. Das Betriebssystem kennt das aktuelle Verzeichnis, weil sie mit „chdir“ dorthin verzweigt sind oder weil sie am gleichen Ort angefangen haben wie der Parent-Prozess, von dem Sie abstammen.
Architektur
Die Art von Computer, mit dem sie arbeiten, wobei eine einzelne »Art« alle diejenigen Computer umfasst, deren Maschinensprache kompatibel sind. Weil Perl Programme einfache Textdateien sind, und keine Ausführbaren Binärprogramme, ist ein Perl Programm wesentlich weniger von der verwendeten Architektur abhängig, als Programme in anderen Sprachen (z.B. C) die direkt in Maschinencode übersetzt werden. Siehe auch Plattform und Betriebssystem.
Argument-Vektor
Argument
Ein Datenelement, das als Eingabe an ein Programm, eine Subroutine eine Funktion oder eine Methode übergeben wird. Das Argument gibt an, was zu tun ist. Es wird auch als »Parameter« bezeichnet.
ARGV
Der Name des Arrays, dass den Argument-Vektor, der Befehlszeile enthält. Wenn sie den leeren <>-Operator verwenden, ist „ARGV“ sowohl der Name des Dateihandles, mit dem die Argumente durchgegangen werden, als auch derjenige des Skalars, der den Namen der aktuellen Eingabe Datei enthält.
arithmetischer Operator
Ein Symbol wie + oder /, mit dem sie Perl anweisen, Arithmetik zu betreiben.
Array
Eine geordnete Sequenz von Werten, die so abgelegt sind, das jeder Wert auf einfache Weise über einen ganzzahligen Index zugänglich ist, der den Offset des Wertes innerhalb dieser Sequenz bestimmt.
Arraykontext
Ein archaischer Ausdruck für etwas, was man genauer als Listenkontext bezeichnen sollte.
ASCII
Wird ganz allgemein für den »American Standard Code for Information Interchange« (einen 7-Bit-Zeichensatz, der nur einfachen englischen Text darstellen kann) verwendet. Wird häufig auch für die unteren 128 Werte der verschiedenen ISO-8859-X-Zeichensätze verwendet (einer reihe untereinander inkompatibler internationaler 8-Bit-Codes). Siehe auch Unicode
Assertion
Siehe Zusicherung
assoziatives Array
Siehe Hash
Assoziativität
Bestimmt, ob zuerst der linke Operator oder der rechte Operator ausgeführt wird, wenn ein Konstrukt wie »A Operator B Operator C« vorliegt und zwei Operatoren den gleichen Vorrang besitze. Operatoren wie + sind links assoziativ, während Operatoren wie ** rechts assoziativ sind.
asynchron
Asynchron sind Ergebnisse oder Aktivitäten, deren relative zeitliche Anordnung nicht vorherzusagen ist, weil zu viele Dinge auf einmal geschehen. Ein asynchrones Ereignis ist also eines, von dem Sie nicht wissen, wann es eintritt
Atom
Eine Komponente eines regulären Ausdrucks die potentiell einen Teilstring erkennt und aus einem oder mehreren Zeichen besteht, die von jedem nachfolgenden Quantifizierer als unsichtbare syntaktische Einheit betrachtet werden. (Das Gegenteil dazu bildet die Behauptung, die etwas mit Nulllänge erkennt und nicht quantifiziert werden kann.)
atomische Operation
Attribut
Aufruf (»Innovation«)
Ausdruck
ausführbare Datei
Ausführen
Ausführungsphase
Ausnahme
Ausnahmebehandlung
Autogenerierung
Autoinkrement
Automatisches Erhöhen einer Zählvariablen (zum Beispiel $i++)
Autoload
Autosplit
Autovivication
AV
awk
Der Name einer alten Textverarbeitungssprache, von der Perl einige Ideen übernommen hat

B

Backtracking
Die praktizierte Variante des Ausspruchs: Aus mathematischer Sicht handelt es sich um die Rückkehr einer erfolglosen Rekursion in einem verzweigten Baum von Möglichkeiten. Backtracking kommt bei Perl vor, wenn ein Muster mit einem regulären Ausdruck erkannt werden soll, und eine frühere Vermutung nicht zutrifft.
Bareword
Ein ausreichendes mehrdeutiges Wort, um es unter „use strict 'subs'“ als ungültig zu betrachten. Fehlt diese Beschränkung, wird ein Bareword so behandelt, als wäre es von Quotingzeichen umschlossen.
Basisklasse
Ein generischer Objekttyp, also eine Klasse, von der sich andere, spezifischere Klassen mit Hilfe der Vererbung ableiten. Wird auch als »Superklasse« bezeichnet.
Bedingungsanweisung
Etwas mit Wenn, aber ohne Aber. Siehe boolescher Kontext.
Befehl
Bei der Shell-Programmierung, die syntaktische Kombination eines Programmnamens mit seinen Argumenten.
Befehlsname
Der Name des gerade laufenden Programms, wie er in der Befehlszeile eingegeben wurde. Bei C wird der Befehlsname dem Programm als erstes Argument übergeben. Bei Perl steht er in der eigens dafür vorgesehenen Variable $0.
Befehlspufferung
Ein Perl-Mechanismus, der nach jedem Perl-Befehl, der eine Ausgabe bewirkt, diese sofort an das Betriebssystem weitergibt. Wird durch das Setzen von $|($AUTOFLUSH) auf einen Wahr-Wert aktiviert. Das ist manchmal notwendig, wenn Daten durch Pufferung ihr Ziel nicht sofort erreichen. Standardmäßig wird bei Dateien oder Pipes mit Blockpufferung gearbeitet.
Behauptung
benannte Pipe
Eine Pipe mit einem im Dateisystem eingebetteten Namen, auf die dann von zwei unabhängigen Prozessen aus zugegriffen werden kann.
Besitzer
Der Benutzer, der (neben dem Superuser) die volle Kontrolle über die Datei hat. eine Datei kann auch einer Gruppe von Benutzern zugewiesen sein, die gemeinsam auf sie zugreifen, wenn der eigentliche Besitzer das erlaubt. Siehe Zugriffsflags.
Betriebssystem
Ein spezielles Programm, das direkt auf der Maschine läuft und so unangenehme Details wie die Verwaltung von Prozessen und Geräten vor Ihnen versteckt. Wird gelegentlich in nicht ganz so strengen Sinne verwendet, um eine bestimmte Programmierkultur zu bezeichnen.
Bibliothek
Eine Sammlung von Prozeduren. In früheren Tagen eine Sammlung von Subroutinen in eine .pl-Datei. Heutzutage wird damit häufig die gesamte Sammlung von Perl-Modulen Ihres Systems bezeichnet.
Big-Endian
Wird auch für Computer verwendet, die das höherwertige Byte eines Wortes an einer niedrigeren Byteadresse ablegen als das niederwerige Byte des Wortes. Siehe auch Little-Endian
binär
Hat was mit Zahlen zu tun, die auf Grundlage der Basis 2 repräsentiert werden, d.h. es gibt grundsätzlich nur zwei Ziffern, 0 und 1.
binärer (dyadischer) Operator
Ein Operator, der mit zwei Operanden arbeitet.
Bindung
Die Zuweisung einer bestimmten Netzwerkadresse an einen Socket
Bit
Ein Integerwert im Bereich von 0 bis 1 einschließlich. Die kleinste zu speichernde Informationseinheit. Ein Achtel Byte
Bitshift
Die Bewegung von Bits in einem (Computer-)Wort nach links oder rechts. Bewirkt eine Multiplikation oder Division mit einer Zweierpotenz.
Bitstring
Eine Folge von Bits, die tatsächlich als Folge von Bits betrachtet wird.
Block
Ein Datensegment von einer Größe, mit der das Betriebssystem gern arbeitet (normalerweise eine Zweierpotenz wie 64 oder 1024). Verweist typischerweise auf ein Datensegment, das von einer Festplatte gelesen, oder geschrieben werden soll.
BLOCK
Ein syntaktisches Konstrukt, das aus einer Sequenz von Perl-Anweisungen besteht, die von geschweiften Klammern umschlossen sind. Die „if“- und „while“-Anweisung sind als „Block“-Konstrukte definiert.
Blockpufferung
Eine Methode, mit der Ein- und Ausgaben effizienter durchgeführt werden, weil jeweils ein ganzer Block verarbeitet wird. Per Voreinstellung führt Perl die Blockpufferung bei Dateien durch, Die auf der Festplatte abgelegt werden. Siehe Puffer und Befehlspufferung.
Boolescher Kontext
Eine spezielle Form des skalaren Kontexts, bei der das Programm nur entscheidet, ob der durch einen Ausdruck zurückgelieferte skalare Wert wahr oder falsch ist. Evaluiert weder als String noch als Zahl. Siehe Kontext
Boolescher Wert
Ein Wert, der entweder wahr oder falsch ist.
Breakpunkt
Ein Punkt in Ihrem Programm, an dem der Debugger die Ausführung anhalten soll.
Broadcast
Das gleichzeitige Senden eines Datagramms an mehrere Ziele.
BSD
Berkeley Standard Distribution – eine Psychoaktive Substanz, populär in den achtziger Jahren, die im Dunstkreis der U.C. Berkeley entwickelt wurde. In vielen Fällen dem verschreibungspflichtigem Medikament namens »System V« ähnlich, aber unendlich viel nützlicher.
Bucket
Ein Punkt in einer Hashtabelle der (eventuell) mehrere Einträge enthält, deren Schlüssel, entsprechend der Hashfunktion auf den gleichen Hashwert abgebildet werden.
Bundle
Eine Gruppe verwandter Module im CPAN.
Byte
Ein in den meisten Fällen aus acht Bits bestehenden Datei.
Bytecode
Eine Mischsprache, die zwischen Androiden gesprochen wird, wenn sie ihre genaue Ausrichtung nicht preisgeben wollen. (Siehe Endian Diese Sprache zeichnet sich dadurch aus, dass sie alles in einer architekturunabhängigen Folge von Bytes darstellen.

C

C
C-Präprozessor
Call by Reference
Call by Value
Callback
Capturing
Client
Cloister
Closure
Cluster
CODE
Codegenerator
code subpattern
Compiler
Composer
Coredump
CPAN
Cracker
CV

D

Datagramm
Datei
Dateideskriptor
Dateiglob
Dateihandle
Dateiname
Dateisystem
Datei-Testoperator
Datensatz
Datentyp
DBM
definiert
Deklaration
Dekrement
Dereferenzierung
Deskriptor
Destruktor
Direktive
Dispatch
Distribution
Dweomer
Dwimmer
dynamsiches Scoping

E

Eigenschaft
einbetten
einfache Vererbung
Einzeiler
eklektisch
Element
en passant
Endian
EOF
erno
Erweiterung
Escapesequenz
exec
Execute-Bit
Exitstatus
Export

F

falsch
FAQ
fataler Fehler
Faulheit
Fehler
Feld
fest eingebaut (built-in)
FIFO
Filter
Flag
Fließkomma
Flush
Fork
formale Argumente
Format
Fortsetzungszeilen
Freeware
Freigabe
frei verfügbar
frei verteilbar
Funktion
Funny Character

G

Garbage Collection
Geltungsvereich (Scoping)
Gerät
GID
gierig
Beschreibt das Verhalten eines Suchmusters in einem regulären Ausdruck. Ein Muster gefolgt von einem Quantifier, welches auf eine Zeichenfolge passt, wird die Länge der passenden Zeichenfolge maximieren. Dies ist das normale Verhalten. Mit einem ? hinter dem Quantifier wird angezeigt, dass der Ausdruck „nicht gierig“ sein soll, also die kürzeste mögliche Zeichenfolge erfassen soll.
Glob
Global
globale Destruktion
Glue Language
„Leimsprache“ – verdeutlicht, dass mit Perl Verbindungen zwischen Anwendungen und Bibliotheken die nicht in Perl geschrieben sind und deren Datenformaten hergestellt werden.
Golf
Programmierwettbewerb, bei dem es darauf ankommt, ein festgelegtes Problem mit möglichst wenig Zeichen Programmcode zu lösen. Für Perl-Programmierer ist dies eine sehr beliebte Form des Wettbewerbs, da die Sprache der Kreativität breiten Raum bietet.
Granularität
grep
Gruppe
GV

H

Hacker
Handler
hängende Anweisung
harte Referenz
Hash
Hashtabelle
Header-Datei
Here-Dokument
hexadezimal
Home-Verzeichnis
Host
HV
Hybris

I

Identifier
Implementierung
Import
Index
indirekt
indirekter Objekt-Slot
indirektes Dateihandel
indirektes Objekt
Indizierung
Infix
Inkrement
Instanz
Instanzvariable
Integer
Interpolation
Interpreter
I/O
IO
IP
IPC
Iteration
Iterator
IV

J

JAPH
»Just Another Perl Hacker«, ein cleveres, aber etwas kryptisches Stück Perl-Code, das bei der Ausführung zu diesem String evaluiert. Wird häuffig zur Illustration eines bestimmten Perl-Features verwendet. Außerdem so etwas wie ein fortwährender »Obfuscated Perl Contest« in Newsgruppen-Signaturen.

K

kanonisch
Kapselung
Klasse
Klassenmethode
Kollationssequenz
Kommandozeilenparameter
Kommentar

Kommentare werden in Perl mit einer # eigeleitet.

Kompilerungseinheit
Kompilerungsphase
Kompilerungszeit
Konstrukt
Konstruktor
Kontext

L

Label
Laufzeit
Laufzeitmuster
Leere-Subklasse-Test
Leftmost longest
lesbar
Lexem
Lexer
lexikalische Analyse
lexikalsiches Scoping
lexikalsiche Variable
LIFO
Link
Linkshift
LISTE
Liste
Listenkontext
Listenoperator
Listenwert
Literal
Little-Endian
logischer Operator
lokal
Lookhead
Lookbehind
Lvalue
Lvalue-fähig
Lvalue-Modifier

M

magisch
magisches Inkrement
magische Variable
Makefile
man
Programm zur Anzeige von Manual-Seiten.
Manpage
Matching
mehrdimensionales Array
In Perl bekommt man mehrdimensionale Arrays nur über Umwege hin, da Perl die Arrays einfach hintereinander hängt und einen einzigen Array bildet. Warum? In Perl ist ein Array nur für skalare Daten vorgesehen!
Lösung: Man baut einen Array von Referenzen auf Arrays. Dies funktioniert wiederum, da Referenzen skalare sind.
Mehrfachvererbung
Member-Daten
Metasymbol
Metazeichen
Methode
Minimalismus
Modifier
Modul
Modulo
Modus
momentan gewählter Ausgabekanal
Monger
mortal
Muster

N

Namensraum
Nebeneffekte
Netzwerkadresse
NFS
Nibble
Heute nur noch selten verwendeter Bergriff für 4 zusammenhängende Bits. Ein Byte (8 Bit) hat ein oberes und unteres Nibble.
Nulllänge
Null-Liste
Nullstring
Nullzeichen
numerischer Kontext
NV

O

Objekt
Offset
oktal
Open-Source-Software
Operand
Operator
Optionen

P

Pad
Paket
Parameter
Parent-Klasse
Parsing
Parsingbaum
Patch
PATH
Der Name bezeicht unter Unix und Windows Betriebssytemen eine Umgebungsvariable mit Pfadangaben zu Verzeichnissen, die ausführbare Dateien enthalten. Trennzeichen unter Unix ist der Doppelpunkt, unter Windows ist es das Semikolon.
Pattern-Matching
perl
Ist die Bezeichnung für das ausführbare Programm, mit und in dem in Perl geschriebene Programme verarbeitet werden. perl für Version 5 der Sprache ist in wesentlichen Teilen in C programmiert. Für die Version 6 gibt es eine Arbeitsversion namens pugs, die in haskell programmiert ist.
Perl
Name der Programmiersprache.
PERL
Von Anfängern und Menschen die Perl nicht mögen, verwendete Schreibweise für Perl oder perl.
Pern
Pfadname
Pipe
Pipeline
Plattform
POD
Polymorphismus
Port
portabel
Porter
POSIX
Postfix
pp
Präfix
Pragma
Pragma Module
Preprocessing
Programm
Programmgenerator
progressives Matching
Protokoll
Prototyp
Prozedur
Prozess
Pseudofunktion
Pseudohash
Pseudoliteral
Public Domain
Zur allgemeinen Verwendung freigegeben. Der Urheber verzichtet auf jegliche Form des Copyrights.
Puffer
Pumpkin
Pumpking
PV

Q

qualifiziert
Die explizite Verwendung eines vollständigen Namens. Das Symbol $Ent::moot ist qualifiziert, $moot ist unqualifiziert. Ein vollständig qualifizierter Dateiname wird vom obersten Verzeichnis aus spezifiziert.
Quantifier
Eine Komponente eines regulären Ausdrucks, die festlegt, wie oft das vorstehende Atom vorkommen darf.
Quellfilter (Source Filter)
Eine Spezielle Art von Modul, das ein spezielles Preprocessing Ihres Skripts vornimmt, bevor es überhaupt zum Tokenizer gelangt.

R

Reaping
Rechtsshift
Referent
Referenz
Regex
Regex-Modifier
reguläre Datei
regulärer Ausdruck
Rekursion
relationaler Operator
reservierte Wörter
RFC
Root
RTFM
Rückgabewert
Rückwärtsreferenz
RV
Rvalue

S

Schleife
Schleifenkontrollanweisung
Schleifenlabel
Schlüssel
Schlüsselwort
Schnittstelle
Scratchpad
Script Kiddie
sed
Semaphor
Sepaerator
Serialisierung
Server
Service
setgid
setuid
Shared Memory
Shebang
Shell
Signal
Signalhandler
Skalar
skalares Literal
skalarer Kontext
skalare Variable
skalarer Wert
Skript
Slice
slurp
Socket
Speicher
Stack
Standard
Standard-I/O
Standardausgabe
Standardeingabe
Standardfehler
Standardwert
start-Strukor
statisch
statische Methode
statisches Scoping
statische Variable
Status
STDERR
STDIN
STDIO
STDOUT
Stream
Subroutine
Symbol

T

Tainted
tatsächliche Argumente
TCP
Teilmuster
Teilstring
Term
Terminator
ternärer (triadischer) Operator
Text
Thread
tie
Token
Tokener
Tokenizing
Toolboxansatz
Transliteration
Trennzeichen
Trigger
troff
Typ
Type-Casting
Typedef
Typeglob
Typemap
typisierte lexikalische Variable

U

Überladung
Überladung von Operatoren
Überschreiben
UDP
UID
Umask
Umgebung
Umgebungsvariable
unärer (monadischer) Operator
Ungeduld
Unicode
Unix

V

Variable
Variableninterpolation
variadisch
Vektor
Verbindung
Vererbung
Verkettung
Verzeichnis
Verzeichnishandel
virtuell
void-Kontext
Vorrang
v-String

W

wahr
Jeder skalare Wert, der nicht zu 0 oder „ “ evaluiert.
Warnung
Eine Nachricht, die an den Stream „STDERR“ übergeben wird, wenn etwas möglicherweise fehlerhaft, gleichzeitig aber nicht so schlimm ist, dass sofort abgebrochen werden müsste. Beachten sie „warn“ in und das Pragma „use warnings“. Siehe auch Pragma Module.
Watch
Watch-Ausdruck; ein Ausdruck, der, wenn sich sein Wert ändert, zu einem Breakpunkt im Perl-Debugger führt.
weiche Referenz
Siehe symbolische Referenz. Gegenteil einer harten Referenz.
Wert
Ein reales Stück Daten im Gegensatz zu all den Variablen, Referenzen, Schlüsseln, Indizies, Operatoren und was man sonst noch so alles braucht, um auf den Wert zuzugreifen.
Whitespace
Ein Zeichen, das dem Cursor bewegt, aber nichts auf ihrem Bildschirm hinterlässt. Typischerweise ein Sammelbegriff für die folgenden Zeichen: Leerzeichen, Tabulator, Zeilenvorschub, Wagenrücklauf und Seitenvorschub.
Wort
Ein Datenstück von der Größe, mit der Ihr Computer am effizientesten umgehen kann, üblicherweise 32 Bit oder ein, zwei Zweierpotenzen mehr oder weniger. In der Perl-Kultur bezeichnet es häufiger einen alphanumerischen Identifier (inklusive Unterstriche) oder einen String, der selbst keine Whitespaces enthält, aber durch Whitespace oder Stringgrenzen von anderen abgegrenzt wird.
Wrapper
Ein Programm oder eine Subroutine, das bzw. die ein anderes Programm oder eine andere Subroutine für sie ausführt und dabei einige seiner bzw. ihrer Ein- und Ausgaben modifiziert, um Ihren Absichten besser dienen zu können.

X

XS
Eine außergewöhnlich exportierte, extrem schnelle, ... Subroutine, die in C oder C++ oder in einer neuen Erweiterungssprache namens XS ausgeführt wird.
XSUB
Eine in XS definierte Subroutine

Y

yacc
»Yet Another Compiler Compiler« Ein Parser-Generator, ohne den es Perl wahrscheinlich nie gegeben hätte. Sehen sie sich die Datei perly.y in der Perl-Quelldistribution an.

Z

Zeichen
Ein kleiner Integerwert, der eine orthografische Einheit repräsentiert.
Zeicheneigenschaft
Eine Vordefinierte Zeichenklasse, die über das Metasymbol erkannt werden kann. Viele Standardeigenschaften sind für Unicode definiert.
Zeichenklasse
Eine in eckigen Klammern stehende Liste von Zeichen. Wird bei regulären Ausdrücken verwendet, um anzuzeigen, dass irgendeines dieser Zeichen an dieser Stelle vorkommen darf. Allgemeiner: jeder vordefinierte Satz von Zeichen, der auf diese Weise verwendet wird.
Zeiger
Bei Sprachen wie C eine Variable, die die genaue Speicherposition eines anderen Objekts enthält. Perl behandelt Zeiger intern, d.h. Sie müssen sich weiter keine Gedanken darum machen. Statt dessen arbeiten Sie nur mit symbolischen Zeigern in Form von Schlüsseln und Variablennamen oder mit harten Referenzen, die keine Zeiger sind (sich aber wie Zeiger verhalten und tatsächlich auch Zeiger enthalten).
Zeile
Bei Unix eine Reihe von null oder mehr Zeichen ohne Zeilenvorschubzeichen, die durch ein Zeilenvorschubzeichen beendet werden. Bei Maschinen, die nicht mit Unix arbeiten, wird dies emuliert, selbst wenn die C-Bibliothek des verwendeten Betriebssystems hiervon andere Vorstellungen hat.
Zeilennummer
Die Anzahl der Zeilen, die vor einer gegebenen Zeile gelesen wurden, plus 1. Perl verwaltet für jedes Script und jede Eingabedatei eine seperate Zeilennummer. Die Zeilennummer des aktuellen Scripts wird durch __LINE__ repräsentiert. Die aktuelle Zeilennummer der Eingabe (für die Datei aus der zuletzt etwas über <DH> gelesen wurde) wird durch $.($INPUT_LINE_NUMBER) repräsentiert. Viele Fehlermeldungen geben, wenn vorhanden, beide Werte aus.
Zeilenpufferung
Wird von einem Standard-I/O-Ausgabestream verwendet, der seinen Puffer nach dedem Zeilenvorschub leer. Viele Standard-I/O-Bibliotheken richten dies automatisch bei Ausgabe ein, die an ein Terminal gehen.
Zeilenvorschub
Ein einzelnes Zeichen, das das Ende einer Zeile repräsentiert. Bei Unix hat es des ASCII Wert 012 oktal (aber den Wert 015 bei Macs) und wird in Perl-Strings durch \n repräsentiert. Bei Windows-Maschinen, die Textdateien schreiben, und bestimmten physischen Geräten wie Terminals wird dieses Zeichen von Ihren C-Bibliothek in einen Zeilenvorschub und einen Wagenrücklauf übersetzt. Normalerweise erfolgt aber keine Übersetzung.
Zirkunfix-Operator
Ein Operator, der seinen Operanden umschließt wie etwa der Zeileneingabeoperator, runde Klammern oder Koalas. (»Zirkumfix« bedeutet als linguistischer Begriff einen Kombination aus Präfix und Suffix. Im Deutschen treten Zirkumfixe z.B. oft in Wörtern wie gesündigt auf. )
Zombie
Ein beendeter Prozess, dessen Parents von „wait“ oder „waitpid“ noch nicht über dessen Ableben informiert wurden. Wenn Sie mit „fork“ arbeiten, müssen Sie beim Beenden Ihrer Child-Prozesse hinter diesen aufräumen, weil sich andernfalls die Prozesstabelle füllt und ihr Systemadministrator mit Ihnen nicht sehr zufrieden sein wird.
Zugriffsflags
Bits, die vom Besitzer einer Datei gesetzt oder gelöscht werden, um anderen Leuten den Zugriff zu erlauben oder zu verweigern. Diese Flags sind Teil des Modus-Wortes, der vom „stat“-Operator zurückgegeben wird, wenn Informationen über eine Datei angefordert werden. Bei Unix-Systemen können Sie sich die Manpage zu ls lesen, wenn sie weitere Informationen über Zugriffsflags wünschen.
Zusicherung
Zuweisung
Eine Anweisung,die den Wert einer Variablen ändert. Syntaktisch wird eine Zuweisung mit einem Zuweisungsoperator notiert.
Zuweisungsoperator
Operator, mit dem eine Zuweisung notiert wird.
Der einfache Zuweisungsoperator ist das Gleichheitszeichen. Wie in anderen Sprachen gibt es auch in Perl zusammengesetzte Operatoren, die zunächst mit dem Wert der Variablen eine Operation durchführen und das Ergebnis dann in der Variablen ablegen.
Beispiele:
# Variable Wert zuweisen
$n = 42

# Variablenwert um drei erhöhen
$n += 3


Installation

Perl ist freie Software. Sie können den Quelltext von Perl von der Seite www.cpan.org herunterladen. Der Quelltext von Perl ist in der Programmiersprache C geschrieben. Wenn ein C-Compiler und genügend Ressourcen vorhanden sind, können Sie den Quelltext selbst in einen lauffähigen Perl-Interpreter übersetzen. Alternativ können Sie vorkompilierte Pakete herunterladen und auf ihrem Rechner installieren.

Auf vielen Systemen ist Perl bereits vorinstalliert

Auf vielen Betriebssystemen wird Perl vom Hersteller oder Distributor mitgeliefert und ist bereits installiert. Dies ist z.B. bei den meisten Linux-Systemen, bei vielen Unix-Systemen und bei Apple's Mac OS X der Fall. Sie brauchen dann nur ein Terminal zu öffnen und

perl -v

einzugeben. Antwortet der Rechner mit

This is perl, v5.10.0 built for i486-linux-gnu-thread-multi

Copyright 1987-2007, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

oder etwas Ähnlichem, so können Sie Perl sofort verwenden.

Vorübersetztes Perl

Erhalten Sie dagegen

perl: command not found

so ist Perl möglicherweise noch nicht installiert.

Allerdings müssen Sie dann immer noch nicht unbedingt selbst Perl übersetzen. Auch hier hat in den meisten Fällen bereits vorher jemand für Sie die Arbeit getan und eine spezielle Binärdistribution erzeugt (ein übersetztes Programm nennt man Binärcode, daher der Name). Dann können Sie eine solche Binärdistribution verwenden. Unter www.cpan.org/ports befinden sich Verweise auf Binärdistributionen für eine Vielzahl von Betriebssystemen. Diese enthalten auch eine Installationsanleitung.

Die Installation einer Binärdistribution ähnelt meist der Installation von anderen Programmen auf einem System und ist daher leicht durchzuführen.

Wenn Sie Microsoft Windows verwenden, kommt neben speziellen Distributionen (siehe Absatz "Perl für Windows") auch die freie Cygwin-Umgebung in Frage, die viele Linux/Unix-Programme enthält, unter anderem auch Perl (www.cygwin.com).

Perl selbst übersetzen

Falls Perl nicht vorhanden sein sollte und eine Binärdistribution nicht in Frage kommt, kann man Perl selbst übersetzen. Dazu muss ein Linux- bzw. Unix-ähnliches Umfeld vorhanden sein, insbesondere ein C-Compiler und Unix-Werkzeuge wie die Shell (sh) oder der Programm-Manager make. MS Windows-Benutzer können hierzu cygwin installieren.

Wenn das installierte Perl älter ist oder bestimmte Funktionen vermisst werden, ist eine eigene Übersetzung auch hilfreich. Neue Funktionen wie Threads oder mehrere Interpreter sind oft in der Standardinstallation nicht implementiert.

Vorhandene Perl-Installation

Ein vorhandenes Perl befindet sich meist in /usr/bin/perl oder /usr/local/bin/perl. Diese Dateien sollten zunächst nicht durch eine eigene Version überschrieben werden, da andere Programme im System gefährdet werden können, insbesondere wenn die neue Version nicht richtig funktioniert oder Funktionen wie Threads fehlen.

Oft darf man als normaler Benutzer die Systeminstallation auch nicht überschreiben. Daher empfiehlt es sich, eine neue Installation im Benutzerbereich vorzunehmen und zu testen. Als Vorschlag wird im Folgenden die Installation in ~/bin und die Perl-Umgebung wie Debugger und Module in ~/perl empfohlen. Die eigentliche Übersetzung wird in ~/src durchgeführt. Hierzu sind keine Systemrechte nötig.

Vorbereitung

Zunächst erzeugen wir die Verzeichnisse ~/bin und ~/perl und sorgen dafür, dass Programme in ~/bin gefunden werden:

cd ~
mkdir -p bin src perl
PATH=~/bin:$PATH
export PATH

oder für C-Shell Benutzer:

cd ~
mkdir -p bin src perl
set path=(~/bin $path)

Entpacken der Quelldateien

Die Datei www.cpan.org/src/stable.tar.gz wird jetzt lokal unter ~/src abgelegt und mit dem tar-Kommando ausgepackt:

cd ~/src
gunzip stable.tar.gz
tar xf stable.tar

Jetzt ist ein Unterverzeichnis, etwa perl-5.8.5, mit den Quelldateien entstanden, in das wir wechseln und die Dateien README und INSTALL betrachten:

ls -F
  perl-5.8.5/
cd perl-5.8.5
less README INSTALL

Möglicherweise existiert noch eine systemabhängige Datei wie README.cygwin oder README.macosx.

Konfiguration

Das Skript Configure kann jetzt ausgeführt werden. Es stellt verschiedene Fragen, wobei die Vorschläge meist übernommen werden können. Auf die Frage nach dem Installationsort antworten wir jedoch statt /usr/local mit ~/perl und die Binärdateien installieren wir ~/bin:

sh Configure.sh 2>&1 | tee log.Configure

Beginning of configuration questions for perl5.

Checking echo to see how to suppress newlines...
...
Installation prefix to use? [/usr/local] ~/perl
... 
Pathname where the public executables will reside? [~/perl/bin] ~/bin
...

Bei allen anderen Fragen kann man zunächst einfach Return drücken.

Es gibt auch die Möglichkeit Configure mit Parametern zu starten.

./Configure -d -s -Dprefix=~/perl

Übersetzung, Test und Installation

Folgendermassen kann man Perl für das eigene System übersetzen, testen und installieren. Dies kann durchaus einige Zeit in Anspruch nehmen (systemabhängig). Der Autor empfiehlt Kaffee zu kochen.

make
...
make test
...
make install
...

Nun sollte Perl installiert sein. Durch folgende Eingabe kann danach der Erfolg ermittelt werden.

~/bin/perl -e 'print "OKAY.\n"'
OKAY.

Wird Okay ausgegeben, wurde Perl erfolgreich installiert und ist lauffähig. Herzlichen Glückwunsch.

Perl für Windows

Falls Sie Perl auf einem Windows-System benutzen wollen, gibt es von ActiveState ein kostenloses vorkompilertes Perl mit Installer, genannt ActivePerl. Von ActiveState kann man auch für Win32 vorkompilierte Module beziehen (über einen in ActivePerl integrierten Paketmanager oder als .zip Archiv).

Für CGI- bzw. mod_perl-Programmierer eignet sich auch gut das XAMPP-Komplettpaket von den Apache Friends. Hier ist bereits ein Apache Webserver, Perl und die Datenbanken MySQL und SQLite (mein Geheimtipp) enthalten. Für Perl-Programmierer gibt es auch ein Add-on mit einer kompletten Perl-Distribution (alle Core Module) und mod_perl.

Links