_________________ ___________ / _____/\_ ___ \\_ _____/ / \ ___/ \ \/ | __) \ \_\ \ \____| \ \______ /\______ /\___ / \/ \/ \/ The German Computer Freaks www.gcf.de Since 1997 /\ / \ ________________________________________________________________________/ # / Perl - Eine Einführung Paper \ / (c) Thorium / GCF (01.05.2003) \/ 1. Einführendes 1.1 Vorwort 1.2 Perl und sein Interpreter 1.3 Einrichten des Interpreters 2. Die Sprache Perl 2.1 Hello World 2.2 Variablen 2.2.1 Skalare 2.2.2 Arrays 2.2.3 Hashes 2.2.4 Geltungsbereiche 2.3 Ein- und Ausgabe 2.3.1 Benutzereingaben 2.3.2 Dateien 2.4 Bedingungen 2.4.1 Die If-Verzweigung 2.4.2 Unless 2.4.3 Vergleichsoperatoren 2.5 Schlaufen 2.5.1 Das Prinzip 2.5.2 While 2.5.3 Until 2.5.4 For 2.5.5 Foreach 2.6 Subroutinen 2.6.1 Einführung 2.6.2 Argumente 2.7 Module 2.8 Referenzen 2.8.1 Grundlagen 2.8.2 Skalare Referenz 2.8.3 Array von Arrays 2.8.4 Array von Hashes 3. Lösungen 4. Nachwort 4.1 Kontakt 4.2 Weiterführende Literatur 4.3 Links 4.4 Dank an 1. Einführendes 1.1 Vorwort So... hier bist du also und willst Perl lernen, wa? Nun gut. Erst ein kleines Vorwort, denn man muss ja schliesslich wissen was man lernen will. Perl ist ne Abkürzung für Practical Extraction and Report Language. Hat also nicht mit Perlen oder so zu tun (rennerwitz). Es wurde anfangs 1987 von Larry Wall (gelobt sei er) entwickelt und steht seiddem unter der GNU Licence. Perl wird vorallem in Linux/Unix bereich ein- gesetzt um kleinere Tools, ersetzungsroutinen oder sonnstige kleine Helferlein zu Scripten, wird also wie z.B. Shellscripte verwendet. Aber Perl kann noch viel viel mehr. Perl wird oft auch im Webbereich eingesetzt (wie PHP, blos das Perl einen sehr viel grösseren Bereich hat, wo es einge- setzt werden kann); man kann damit GUI's Scripten, es gibt Tonnenweise Module (zu finden auf www.cpan.org) und die Community ist wohl die geilte weit und breit, da Perl Programmierer den krampfhaften Drang haben zu helfen. Desshalb auch sitze ich hier und Schreibe dieses Tutorial, um euch einen Einblick in die Welt eines Perl'ers zu geben und mir die Langeweile zu vertreiben... So long... 1.2 Perl und sein Interpreter sub glossar_Interpreter { print 'Ein Interpreter ist ein Programm, welcher einen Code oder Text in einen anderes Format umwandelt. In der Pro- grammierung heisst das, dass der Perlcode in eine für den Computer verständliche Form gebracht wird, welche dann aus- geführt werden kann. Der Unterschied zum Compiller ist dieser, dass der entstehende Maschinencode nicht gespeichert wird und wiederverwendet werden kann.'; } Perl ist eine Interpretierte Spache, was heisst, dass der Code nicht erst in Maschinensprache compilliert werden muss, sondern direkt vom Interpreter übersetzt wird. Das hat sowohl vor, wie auch Nachteile. Einerseids ist ein Ändern und Ar- beiten mit Perl ziemlich bequem, da man für jedes Script genau eine File hat (ausgenommen Modulen u.s.w) andererseids kann man den Code des Scripts auch vom Script ändern lassen, was meiner Meinung nach auch Hilfreich ist. So kann man z.b. ein Modul ändern, wärend ein anderes Script darauf zugreifft und das Modul dann vom noch laufenden Script neu laden lassen. Somit sich änderungen zur Laufzeit möglich (auch wenn nur in beschränkten Masse). Ein weiterer Vor- (oder Nach- teil) ist die Tatsache, dass Scripts für jeden einsehbarsind (ausser das Script läuft Serverseitig auf einem Webserver). Dies fördert Opensource und es ist möglich auf eine riesige Palette von verschiedensten Perlscripten zuzugreiffen und Ideen zu sammeln (oder Codeklau zu betreiben). Ein Nachteil der interpretierten Sprache ist jedoch, dass jeder der das Script ausführen möchte, einen Perl Interpreter braucht. Dieses Problem wurde aber von verschiedenen Seiten schon er- kannt, und es gibt diverse, weniger 'offiziele' Programme die Perl z.b. in C code umwandeln (welcher dann Compilliert werden kann), oder Programme wie "perl2exe" die einfach zu einer exe den Interpreter hinzupacken. In Perl6 (gerade kam Perl 5.8.0) raus, verbreitet ist aber dennoch Perl 5.6.1) soll aber dann ein Perleigener Compiller beiliegen. Den mehr oder minder offiziellen Interpreter für Windows bekommt ihr unter http://www.activestate.com. Solltet ihr unter Linux arbeiten (oder unter Unix) ist wahrscheinlich Perl schon vorhanden. Einfach in die Shell und "perl -v" tippern. 1.3 Einrichten des Interpreters Wenn ihr den Perlinterpreter installiert habt, testet ihr es mit "perl -v". Unter Windows geht ihr dazu mit Start / Ausführen und "cmd" (Unter 2k/XP) oder "command" (Unter 9x/ME) in die DosEmu. Hier gebt ihr: "perl -v" ein. Es sollte eine Versionsmeldung über Perl sowie lizenzbestimmungen zu sehen sein. Falls das nicht so ist, schaut bitte zuerst ob die PATH variable richtig gesetzt wurde (dazu gebt ihr in dieser Dos- Emulation ein: "echo %PATH%". Dann kommt eine Zeile die ungefähr so aussieht: " C:\Perl\bin\;C:\JDK\bin;C:\WINNT\system32;C:\WINNT;C:\WINNT\System32\Wbem;C:\PROGRA~1\ULTRAE~1 " Hier sollte nun der Pfad zu eurer Perlinstallation drinstehen. Bei mir ist das C:\Perl - der Interpreter "perl.exe" befindet sich im Subdir "bin". Ist das nicht der Fall, fügt es einfach hinzu mit: "set PATH=%PATH%;C:\Pfad\zu\Perl\bin". Wenns jetzt nochned läuft, fragt den nächsten Informatiker oder Mailt mir: thorium@gcf.de ^^ Unter Linux halt einfach "perl -v", wenn das ned klappert schaut erstmal, ob die Perl-binary da ist (standard- mässig in /usr/bin). Wenn ned, macht mal nen find bzw locate unter Linux (Unix "find / -name "perl" -print" oder Linux "locate perl"). Wenn das ned so ist, fragt den nächsten mit nem "ich root du nix" T-shirt. 2. Die Sprache Perl 2.1 Hello World Jetzt packenwer unseren Lieblingseditor aus (Unter Windows bitte nicht Notepad, da der Probleme mit den Zeilen- umbrüchen macht. Benutzt stattdessen besser WordPad im Plaintext modus oder UltraEdit (einer der Besten Editoren den ich kenne www.ultraedit.com) ) und packen folgendes da hinein: helloworld.pl ====================================================================== #!/usr/bin/perl -w use strict; print "Hello World!\n"; ====================================================================== So, nun abspeichern (z.b. unter dem Dateinamen "helloworld.pl") und wenn ihr auf nem *nix system seid, noch nen "chmod 755 filename" - damit macht ihr es ausführbar. Nun "cd"ed ihr auf der DosBox oder in der Shell in das Verzeichnis und führt das Perlscript aus. Entweder mit "perl filename.pl" oder (Unter Win: "filename.pl", *nix mit "./filename.pl"). Die Ausgabe sollte mehr oder weniger so aussehn: Ausgabe helloworld.pl ---------------------------------------------------------------------- H:\perltut>perl helloworld.pl Hello World! ---------------------------------------------------------------------- Nun, was ist hier passiert? sub grundlagen_der_programmierung { print 'Ein Programm ist so aufgebaut, dass es von oben bis unten zeilenweise ausgeführt wird. Ihr müsst euch um es besser zu verstehen (vorallem bei grossen Programmen) in ein Programm einführen *g*. Ihr springt Gedank- lich von Zeile zu Zeile und denkt, was diese Zeile bewirkt, und geht dann zur nächsten u.s.w. Einige Zeile be- wirken auch Sprünge zu einer Zeile und wieder Zurück, so das kompliziertere Gebilde entstehen, doch dazu kommen wir später'; } Die Erste Zeile ist ein Kommentar und nur für *nux Systeme relevant. Man nennt sie liebevoll die Shebang. Es zeigt einem *nix System, wo der Interpreter dieses Codes liegt. In diesem Falle ist es also "/usr/bin/perl". Windowssysteme ignorieren diese Zeile ganz einfach. Kommentare werden demnach mit # geschrieben. Der Interpreter ignoriert alles von # an, bis zum nächsten Zeilen- sprung (also Ende der Zeile). Die Zweite Zeile "use strict;" lädt ein Modul, dass uns zwingt gewisse Dinge zu tun wie Variablen deklarieren u.s.w. Es ist so, dass man in Perl verdammt viele freiheiten hat. Diese Freiheit wird einem aber manchmal zum Verhängnis wesshalb man gerne das "strict" modul lädt. Was genau ein Modul ist und wozu man es sonnst noch braucht, kommen wir später. Die Wohl relevante Zeile im Script ist die 4. 'print "Hello World!\n";' Was print bedeutet is wohl jedem klar... print gibt angegebene daten (standardmässig) in STDOUT (Standardoutput, also die Console) aus. Eine Zeichenkette wird in '' (nicht interpretiert) oder in "" (interpretiert) eingeschlos- sen. Somit ist das \n ist ein Sonderzeichen. Jedes Zeichen nach einem "\" wird besonders behandelt und hat eine besondere Bedeutung. So z.b. hier das \n steht für einen Zeilenumbruch. \t für den Tabulator und \\ für ein normales "\". Genauso weren in "" Variablenamen als ihr Wert und nicht blos als der Name der Variable angesehn. Am Ende des Befehles sehen wir noch ein ";" - dieses Zeichen schliesst den Befehl, wie jeden anderen auch, ab. 2.2 Variablen 2.2.1 Skalare sub grundlagen_der_programmierung { print 'Variablen muss man sich wie eine Box vorstellen, in welche man etwas reinlegt, rausholt, anschaut, umschreibt oder einfach wieder vernichtet. Man hat in einem Programm meist mehrere dieser Varialeboxen welche jede einen unterschiedlichen Namen haben müssen. Man kann mit Variablen auch rechnen, oder sie als Textbau- steine verwenden.'; } Skalare Variablen sind die einfachste Form der, in Perl vorkommenden, Variablen. Sie halten einen einfachen Text oder eine Zahl. Dabei muss kein Typ festgelegt werden, wie in anderen Programmiersprachen wie Java oder C. Ähnlich wie in anderen Programmiersprachen, werden Skalare mit einem "$" gekennzeichnet. Als Variabelnamen dürfen alle Zeichen ausser denen mit besonderer Bedeutung (z.B. \ * $ @ oder %) herhalten. Das heisst man darf unter anderem sowohl ä, ö und ü wie auch _ und alle Zahlen verwenden. Nur bei einstelligen Variablenamen ist Vorsicht geboten, denn es gibt einige Variablen (wie z.b. $_ und $") die reserviert sind. ====================================================================== $zahl1 = 23; # Die Variable "zahl1" mit dem Wert 23 füllen $zahl2 = 51; # Dasselbe mit "zahl2" und 51 $resultat = $zahl1 + $zahl2; # Das Resultat von 23 + 51 in "$resultat" speichern $text1 = "Hallo "; # Definiere eine Textvariable $text2 = "Welt!\n"; # Mit sonderzeichen $resultat = $text1 . $text2; # Und füge diese zwei dann, zu "Hallo Welt!\n" zusammen $resultat = $text1, $text2; # Gib erst das eine, und dann das andere aus. Führt zum gleichen wie oben :) # Siehe hierzu auch später Listen im Kaptiel 2.2.2 Arrays $resultat = "$text1$text2"; # Dasselbe, nur nochmal anders ====================================================================== Integer (Also Zahlen), Fliesskommazahlen sowie Strings gleiten sanft ineinander über. Wenn mit einem Text gerech- net wird, wird er ganz einfach in seinen Integerwert umgerechnet. So werden von Anfang des Strings alle Zahlen als Integer (wenn ein "." vorkommt, als fliesskommezahl) angenommen. Sobald ein Buchstabe folgt, wird der Rest verworfen. Wenn mit "use strict;" gearbeitet wird (so wie in 2.1 beschrieben) wird man gezwungen Variablen zu initiieren. Dies geschiet mit dem Operator "my". ====================================================================== my $variable1; # Variable initiieren $variable = 'Wert'; # und einen Wert zuweisen my $variable2 = 'Wert'; # Dasselbe ====================================================================== 2.2.1.a Übung Was gibt der folgende Code aus? ====================================================================== #!/usr/bin/perl use warnings; use strict; my $text2 = "Perl is"; my $text1 = 'oll \n'; my $zahl1 = 52; my $zahl2 = 5.000; print $text2, "t t$text1", $zahl1 + $zahl2, "\n"; ====================================================================== 2.2.2 Arrays Eine etwas komplexere, aber auch mächtigere Form ist das Array. Dieses entspricht einer Liste, also einer Reihe verschiedener Skalaren. Die Skalare werden mit einem Index voneinander unterschieden, der bei 0 beginnt, und dann für jedes Element inkrementiert (also um eins erhöht) wird. ====================================================================== my @array = ("Element 0", 1, "Das Element 2", "Hier das 3."); # Array mit 4 (3 + das nullte) Elementen erstellen $array[2] = "Ein anderes 2. Element"; # Das 2. Element (Also das, an 3. Stelle) ändern. print $array[1]; # Das Element mit Index 1 ausgeben: '1' ====================================================================== Um Elemente hinzuzfügen und Wegzunehmen gibt es auch Operatoren ====================================================================== my @array = ("Element 0", 1); push(@array, "Das Element 2"); # Hinten anstellen push(@array, "Nummer 3", 4, 5); # Das Array ist hier: "Element 0", 1, "Das Element 2", "Nummer 3", 4, 5 pop(@array); # Hinten wegnehmen. Das Array trägt nun das letzte Element _nicht_ mehr. my $lastelementh = pop(@array); # Popt das letzte Element ab, # und füllt die Variable "$lastelementh" mit dessen Wert. my $first = shift(@array); # Entfernt das erste Element und weist es zu unshift(@array, $first); # Fügt den Wert wieder vorne hinzu my @array = reverse(@array); # Kehrt das Ganze Array um. Hier ist das erste dann das letzte u.s.w ====================================================================== 2.2.2.a Übung Schreibe eine Routine, die mit Hilfe von pop und push den Wert "t" an der 7. Stelle einfügt @array = ("P", "e", "r", "l", "i", "s", "t", "o", "l", "l"); 2.2.3 Hashes Die höchste Form der Elemente ist das assioziative Array (oder Hash ;) ). Es funktioniert nach dem Schlüssel-Wert prinzip. Beim Array wurden uns die Keys (also Indexes, 0, 1, 2, 3 u.s.w vorgegeben. Beim Hash suchen wir uns die Schlüssel selber aus, und können die Werte dann, anhand dieses Keys erreichen. Ein Beispiel: ====================================================================== my %hash = ( 'Pferd' => 'grau', 'Ferkel' => 'lila', 'Gorilla' => 'braun', 'Esel' => 'grau'); ====================================================================== Hier wird ein Hash mit dem Namen "hash" initialisiert. Es Fasst die Schlüssel Pferd, Ferkel, Groilla und Esel welchen jeweils ein Farbwert zugeteilt wurde. Ein Schlüssel (also hier Tier) darf nur einmal vorkommen. Sollte es erneut definiert werden, wird der alte Wert überschrieben. Werte sind untereinander nicht verbunden, und dürfen jegliche Werte annehmen, unabhängig davon, was andere Werte besitzten. ====================================================================== my %hash = ("Pferd" => "grau"); # Hash initiieren $hash{'Ferkel'} = "lila"; # Schlüssel "Anderer Schlüssel" mit Wert "Anderer Wert" hinzufügen. print $hash{'Ferkel'}; # Wert des Schlüssels "Ferkel" abfragen: 'lila' ====================================================================== Der Operator "=>" ist gleichbeeutend mit einem "," und dienst nur des besseren leserlichkeit. Mit Hashes kann man schnell, einfache Datenmodelle erstellen wie z.b. Benutzer / Passwort Listen und anderes. Es ist auch möglich Hashes zu verschachteln, bei welcher dann ein Wert wiederum ein Schlüssel ist, oder eine Liste. Doch dazu später. 2.2.3.a Übung Welche Schlüssel und Werte enthält %hash2 nach diesem Codeblock? ====================================================================== my %hash, %hash2; $hash{1} = 'Wasser'; $hash{2} = 'fall'; $hash2{$hash{1}.$hash{2}} = 'schön'; $hash2{$hash2{$hash{1}.$hash{2}}} = 'gut'; ====================================================================== 2.2.4 Geltungsbereiche Variablen die mit my definiert wurden, gelten nur in ihrem und den unterlegenen Blöcken, was heisst, dass eine Variable welche in einer Schlaufe definiert wurde, ausserhalb dieser nicht mehr exisiert. Ein aufrufen dieser würde zu einem Fehler führen: ====================================================================== { my $hans = 2; { my $heidi = 24; print $hans; # Ok { print $heidi, $hans; # auch Ok } } print $heidi; # Fehler, Variable gilt hier nicht mehr } ====================================================================== 2.3 Ein- und Ausgabe 3.3.1 Benutzereingaben So wir wissen nun zwar, was Variablen sind, aber was nutzt uns das? Im Moment noch nichts, aber jetzt fängts an, cool zu werden. Benutzereingaben: ====================================================================== my $eingabe; # Variable definieren $eingabe = ; # Standard-Input (STDIN, hier Tastatus) lesen chomp($eingabe); # Das \n am Ende der Zeile löschen ====================================================================== Nun, was passiert hier? Den Hanlder kann man sich wie eine Röhre in einer Wand vorstellen, die mit dem Anderen Ende an der Tastatur angemacht ist. Immer wenn der User nun etwas eingibt, flutschen die Buchstaben durch das Rohr. Die Eingabe hört dann auf, wenn ein "Enter" durchgeschickt wird. Dieses Enter wird aber mitgenommen in die Variable, wesshalb wir nach der Eingabe die Zeile + ein "\n" in unserer Var haben. Das wollenwer natürlich nicht, wesshalb wir es auch Prompt mit einem "chomp" abschneiden. Der befehl chomp löscht ganz einfach ein \n am Ende der Zeile. Ist keines vorhanden, macht er nichts. Also wir können nun also Benutzereinhaben abfangen, doch ist das nicht einwenig aufwendig? Naja Perl, wär nicht Perl wenn es auch einfacher ginge: ====================================================================== chomp(my $eingabe = ); ====================================================================== Das ist doch mal kompakt ^^. Die Benutzereingabe kann nun genau wie eine Variable weiterverwendet werden. Da der User aber eingeben kann, was er will, muss man, vorallem bei komplexeren Programmen darauf achten, dass man auf alles Vorbereitet ist, was der User (nicht) eingibt, um dann nicht so wie M$'s NetBios von Win9x zu enden, dass zusammenbricht, wenn nicht das kommt, was es erwartet (Guter alter Ping of Death ^^). 2.3.1.a Übung Schreibe ein Programm, welches den Benutzer nach seinem Namen fragt, und ihn dann mit diesem begrüsst. 3.3.2 Dateien Dies ist ein Kapitel, dass am Anfang noch nicht so wahnsinnig von Interesse sein dürfte, aber ich hab es trotzdem mal hier reingenommen, da es auch zu In- und Ausgabe gehört. Um aus einer File zu lesen, oder in eine File zu schreiben, müssen wir einen Handler generieren. Also eine neue Röhre in die Wand schlagen, durchdie wir Informationen austauschen können. Dies geschieht mit dem Befehl open: ====================================================================== my $dateipfad = "/home/perl/datei"; # Ein Filepfad wird angegeben $dateipfad = "c:/perl/datei"; # Und auf einen Windowsfilepfad umgeschrieben. Zu beachten sind hie die Vor- wärtsslashes, mit denen es wesentlich einfacher geht als jedesmal 2 Backslashes zu machen. $dateipfad = "./datei"; # Oder einfach Relativ zum aktuellen Verzeichnis angeben open (FILEHAND, "< $dateipfad"); # Dateihandler wird zum Lesen geöffnet ("<", also von File weg) my @fileinhalt = ; # Der Inhalt wird in ein Array gelesen, wobei jede Zeile einem Element des # Arrays entspricht close (FILEHAND); # Und nicht zu vergessen, den Handler wieder zu schliessen um die Datei frei- # zugeben ====================================================================== Also jetzt haben wir im Array: @fileinhalt die gesammte Datei Zeile für Zeile gespeichert. Ist das ned cool? Nun können wir damit Arbeiten. Dringenst zu empfehlen, aber leider immer wieder vergessen ist der || die() - Teil: ====================================================================== open (FILEHAND, "< $dateipfad") || die("Konnte Datei nicht öffnen. Fehlerbeschreibung: $!"); ====================================================================== Nun, jede Funktion in Perl gibt einen wahren Wert (meist 1) zurück, den man weiterverarbeiten kann. Der || (OR - logisches Oder) führt den nächsten rechtsliegenden Befehl aus, wenn der vorherige Fehlschlägt (also undef oder 0 zurückgibt). Wenn also die Datei nicht geöffnet werden kann, wird die() ausgeführt, was das Perlscript dann, mit einer schönen Fehlermeldung, stebren lässt. Die Variable $! ist eine Spezialvariable, welche Fehlermeldungen fasst. Ihr habt also dann immer eine schöne Fehlermeldung wieso etwas schiefgelaufen ist. Witzig ist auch noch ein "\n" vor dem Ende von die. Also: die("Irgendwas\n"); Das blendet die Zeilennummer des Fehlers aus, und macht das ganze einweinig Professioneller. Es ist dann aber umso wichtiger, dass ihr eine genaue Fehlermeldung absetzt. Das schreiben funktioniert ungefähr gleich: ====================================================================== my $dateipfad = "./datei"; open (FILEHAND, "> $filepfad) || die($!); # Öffnet einen Filehandler zum Überschreiben print FILEHAND "Eine Zeile\nUnd eine Zweite\nUnd dritte\n"; close (FILEHAND); open (FILEHAND, ">> $filepfad) || die($!); # Öffnet einen Filehandler um dann hinten anzuhängen print FILEHAND "Eine vierte Zeile\n"; close (FILEHAND); ====================================================================== Hier ist neu, dass print einen Handler annimmt. Normalerweise verwendet, wenn nichst anderes angegeben, STDOUT und $_ als Argumente. STDOUT ist der Standardoutput also die Console und $_ ist die Standardlaufvariable von Perl. Wenn kein Handler angegeben ist, printet print einfach in die Console. Die Möglichkeit aber, auch andere Handler anzugeben, ist IMHO eine wunderschöne Lösung für dieses Schreibproblem. Man kann auch ein array in print schmeissen, was uns ermöglicht, mit dem Einen Schritt aus einer Datei auszulesen, und dann den gleichen Inhalt in eine Andere zu schreiben. Also quasi ein copy-Befehl. ====================================================================== print FILEHAND @fileinhalt; ====================================================================== Gerne wird in Verbindung mit Dateien der split und join Operator gebraucht. split teilt einen Skalaren Wert anhand eines Zeichens in ein Array ein. join führt ein Array getrennt durch ein Zeichen wieder zu einem skalar zusammen. Ein Beispiel: ====================================================================== my $namenliste = 'hans+peter+heidi+ivan'; my @namen = split(/+/, $namenliste); # An "+" trennen $namenliste = join('&', @namen); # Mit "&" wieder verbinden # $namenliste ist hier 'hans&peter&heidi&ivan' ====================================================================== 2.4 Bedingungen 2.4.1 Die If Verzweigung So wir können also nun Ein und Ausgeben, doch wie reagieren wir auf Benutzereingaben? Das geht mit verschiedenen Wegen. Der Einfachste und wohl am meisten gebrauchte Weg ist die 'If'-Verzweigung. If braucht als Argumente einen Ausdruck, der Wahr oder Falsch (1 oder 0, true oder false, u.s.w) ausgibt. Wenn das Argument Wahr zurückgibt, wird der Codeteil der von { } umgeben wird, ausgeführt. Wenn nicht, wird einfach nach diesem Block weitergemacht: ====================================================================== if ($jahr > 2000) { print "Wir haben bereits das 21. Jahrhundert erreicht!\n"; } ====================================================================== Der Ausdruck "if" lässt sich mit "Wenn" übersetzen (wie es Microsoft auch tut :P). Also Wenn die Variable $jahr grösser ist als 2000, dann wird der Satz ausgegeben. Wenn das Jahr kleiner ist, passiert einfach nichts. Wie hier gezeigt, wird das Argument von einfachen Klammern umgeben. Man kann auch mehrere Bedingungen mit einem logischen UND oder ODER verknüpfen: ====================================================================== if (($jahr > 2000) && ($jahr <= 2100)) { print "Wir haben das 21. Jahrhundert!\n"; } ====================================================================== Also Wenn das Jahr grösser als 2000 UND kleiner oder gleich 2100 ist, dann gib den Satz aus. Wie beschrieben ist derOperator für das logische UND ein &&. Das logische ODER wird mit || gekennzeichnet. Hier muss dann jeweils blos eines der beiden (oder beide) Bedingungen erfüllt sein. Doch können wir auch darauf reagieren, wenn die Bedinungung nicht erfüllt ist? Selbstverständlich ;) ====================================================================== if ($jahr > 2100) { print "Wir haben das 22. Jahrhundert erreicht!\n"; } elsif ($jahr > 2000) { print "Wir haben das 21. Jahrhundert erreicht!\n"; } else { pritn "Wir sind noch nicht im neuen Jahrtausend!\n"; } # Ende If ====================================================================== Hier sind neu "elsif" und "else". Diese lassen sich mit "Andererseids, wenn" und "Andernfalls" übersetzen. Das ganze heisst also ausgedeutscht: Wenn das Jahr grösser als 2100 ist, dann sage wir erreichten das 21. Jahrhudnert, wenn nicht dann schau doch mal, ob das Jahr schon grösser als 2000 ist. Wenn ja, dann gib mal "21 jahrhundert" aus, wenn nein, dann sag wir leben noch in der Steinzeit. Eines dieser Sätze wird auf jedenfall ausgegeben. Aber blos einer. Natürlich ist das Jahr auch grösser als 2000 wenn das Jahr grösser als 2100 ist, doch das ist irrelevant, denn Perl macht, wenn eine lösung gefunden wurde, nach dem "Ende If" weiter. Man kann in einen If Block natürlich auch mehrere Befehle hereinpacken (wie in jeden andern Block auch) es gibt jedoch eine Schreibform, die sich besonders dafür eignet, blos einen Befehl ausgeben. ====================================================================== print "Die Variable \$msg ist vorhanden!\n" if ($msg); ====================================================================== Wie man sieht, steht hier der Print mehr im Vordergrund und sticht heraus. Das ganze ist aber gleichbedeutend mit: ====================================================================== if ($msg) { print "Die Variable \$msg ist vorhanden!\n" if ($msg); } ====================================================================== Nun, was ist denn hier los? Wo bleibt der Vergleich? Nun, Perls 'If'-Verzweigung nimmt nicht nur einfache Vergleiche als Bedingung an, sondern nimmt auch ganze Befehlsketten als Bedingung. So z.b. eine Zuweisung. Denn jeder Perl Befehl gibt, wenn er erfolgreich war einen 'true' Wert (1) zurück. Wenn er fehlschlug einen 'false' also 0 oder undef Wert. Eine Zuweisung, die einer Variable den 'undef' (also weniger als '') zuweist, ist ungültig und gibt somit einen 0 Wert zurück. Dies kann man ausnutzen, wenn man z.b. ein Objekt einer Datenbankanbindung erzeugt. Schlägt dieser Versuch fehl, so wird dem Objekt der undef Wert zugewiesen, was dann abegfangen werden kann. Dieses Abfangen von Fehlern kennen wir aus '3.3.2 Dateien': open (FILEHAND, "> $filepfad) || die($!); Der Operator "open" gibt 'false' zurück, wenn beim Öffnen der Datei ein Fehler verursacht wird. Desshalb lässt sich der Fehler auch folgendermassen abfangen: ====================================================================== if (open (FILEHAND, "> $filepfad)) { print "Öffnen erfolgreich!\n"; } else { die("Fehler beim öffnen von $filepfad: $!\n"); } ====================================================================== 2.4.2 Unless Der Gegenspieler zu If ist unless. Hier wird der Block ausgeführt, wenn die Bedingung einen Falschen Wert (undef|0) zurückgibt. Also lässt sich unser Dateiöffnungsbeispiel auch so lösen: ====================================================================== unless (open (FILEHAND, "> $filepfad)) { die("Fehler beim öffnen von $filepfad: $!\n"); } die("Fehler beim öffnen von $filepfad: $!\n") unless (open (FILEHAND, "> $filepfad)); # Das selbe if (!(open (FILEHAND, "> $filepfad)) ) { die("Fehler beim öffnen von $filepfad: $!\n"); } # Ebenfals das selbe ====================================================================== Beim letzten Beispiel gibt sich der '!' Operator zu erkennen. Dieser kehrt einfach ein Nachfolgendes "Wahr" in ein "Falsch" um und umgekehrt (Logisches NICHT). 2.4.3 Vergleichsoperatoren Operator | Bezeichung ---------------------------------------------------------------------- == | Nummerisches gleich (nur Zahlen, Zeichenketten mit 'eq' bzw 'ne' vergleichen!) != | Nummerisches ungleich < | Nummerisches kleiner als <= | =< | Nummerisches kleiner als oder gleich (2 Formen) > | Nummerisches grösser als >= | => | Nummerisches grösser als oder gleich (2 Formen) eq | String gleich (equal) ne | String ungleich (not equal) && | Logisches AND (Verknüpfen von Bedingungen) || | Logisches OR (Verknüpfen von Bedingungen) ! | Logisches NOT (Negieren von Bedingungen) ---------------------------------------------------------------------- 2.5 Schlaufen 2.5.1 Prinzip Nun können wir also Vergleichen. Doch wie bilden wir etwas wie "Solange die Eingabe falsch ist, gib "Blöp" zurück"? Hier kommen die Schlaufen ins Spiel. Es gibt verschiedenste Arten von Schlaufen - while, until, for, foreach sind wohl die gebräuchlichsten. Im Prinzip ist eine Schlaufe nichts anderes, als eine ständige Wiederholung ein und des- selben Blocks solange oder bis eine Bedingung erreicht ist. 2.5.2 While Die While Schlaufe wird in den meisten Büchern und Tutorials als erstes erklärt. Naja, so will ich es auch tun ;) While bedeutet soviel wie "Solange" - Führt also eine Schlaufe solange aus, bis eine Bedingung ungültig wird. Ein Beispiel: ====================================================================== my $eingabe = ""; while ($eingabe ne "richtig") { print "Die Eingabe ist Falsch\n"; print "Wie lautet der richtige Wert? "; chomp($eingabe = ); } ====================================================================== Hier wird die Schlaufe also ausgeführt, solange die eingabe nicht "richtig" ist. ($eingabe ne "richtig" (ne für not equal wie in 2.3.3 erklärt)). Weniger schön ist hier natürlich, dass bevor der User eine eingabe machen kann, er schon ein "Die Eingabe ist Falsch" an den Kopf geworfen bekommt. Dem kann abgeholfen werden, indem man eine Abfrage vor die Schlaufe stellt: ====================================================================== print "Wie lautet der Wert? "; chomp(my $eingabe = ); while ($eingabe ne "richtig") { print "Die Eingabe ist Falsch\n"; print "Wie lautet der richtige Wert? "; chomp($eingabe = ); } ====================================================================== Hier wird also immer am _Anfang_ der Schlaufe überprüft, ob die Bedingung richtig ist. In der Schlaufe selber darf die Bedingung auch mal falsch sein, solange sie am Ende (wo wieder zum Anfang gesprungen wird ;)) wieder richtig ist. Wenn man die Bedingung also ans Ende der Schlaufe stellt, wird diese mindestens einmal durchlaufen, ohne festzustellen ob die Bedingung richtig ist: ====================================================================== do { print "Blubb\n"; } while (1 == 0) ====================================================================== 1 ist natürlich niemals 0. Doch dennoch wird ein Blubb angezeigt, da wie erwähnt, erst am Ende der Schlaufe bestimmt wird, ob ein erneutes Durchlaufen der Schlaufe nötig ist. 2.5.2.a Übung Mit dem jetzigen Wissenstand ist man in der Lage ein kleines Spiel zu programmieren - Das Zahlenraten. Dabei wird eine Zufällige Zahl kreiiert (für eine ganze Zahl zwischen 1 und 100: my $randomno = int(rand(100) + 1); ). Der Spieler muss nun diese erraten und kann einen Tipp abgeben. Ist der Tipp falsch, wird dem Spieler mitgeteilt ob die Zahl grösser oder kleiner als die Gesuchte ist. Wenn man will, kann man dem ganzen noch einwenig schnickschnack hinzufügen wie Versuce zählen und Frage, ob man nochmal Spielen will u.s.w 2.5.3 Until Wie If den Gegenspieler Unless, hat auch While einen Gegenspieler. Dieser heisst Until. Wie die deutsche Übersetzung schon sagt, wird hier die Schlaufe beendet, sobald die Bedingung richtig ist. Unser vorheriges Beispiel liesse sich also auch schreiben: ====================================================================== print "Wie lautet der Wert? "; chomp(my $eingabe = ); until ($eingabe eq "richtig") { print "Die Eingabe ist Falsch\n"; print "Wie lautet der richtige Wert? "; chomp($eingabe = ); } ====================================================================== Man beachte hier, dass das 'ne' durch ein 'eq' für equal, also gleich ersetzt wurde. Die Schlaufe funktioniert nun genauso wie vorhin, nur, dass sie vielleicht ein kleinwenig leserlicher wurde. 2.5.4 For Nun, da es oft vorkommt, dass man eine Schlaufe wie diese haben möchte: ====================================================================== my $i = 0; # Diese 666. Zeile widme ich meiner Freundin und Mephisto *lol* while ($i < 7) { print $i; $i++; # Dasselbe wie "$i += 1" und dasselbe wie "$i = $i + 1" also ein Increment. } ====================================================================== gibt es einen eigenen Schlaufentyp für dieses Gebilde. Die for-Schlaufe: ====================================================================== for (my $i = 0; $i < 7; $i++) { print $i; } ====================================================================== Die for-Schlaufe nimmt also 3 Argumente getrennt durch ";". Das erste ist eine Definition, die vor dem erstem Durch- lauf ausgeführt wird. Hier kann stehen was will, auch ein einfacher print ""; oder einfach nichts. Es bietet einfach einen Platz, um die Variabledefinition unterzubringen. Das zweite Argument ist die Bedingung. Die Schlaufe wird solange ausgeführt, bis diese Bedingung (eingegrenzt durch zwei ;) wahr zurückgibt. Das dritte Argument ist jenes, dass am Ende der Schlaufe ausgeführt wird. Hier also ein einfacher Increment der $i Variable. Ausgedeutscht bedeutet die Schlaufe also: Gebe alle Zahlen, beginnend bei 0, aus, die kleiner als 7 sind, in einem Schritt von 1 (Also die Zahlen 0 bis 6). Da die drei Argumente beliebig eingefüllt werden können, dürfen darin auch Berechnungen vorkommen wie z.B: for (my $i = ($y - 2) * 5;$i <= 152 / 2; $i *= 1.5) { Immer gerne wieder Benutzt ist die Schlaufe in Verbindung mit dem Array: ====================================================================== my @startnummern = ("Peter", "Hans", "Heidi", "Ueli", "Rosa", "Majid"); for (my $i = 0; $i <= $#startnummern; $i++) { print "Die Startnummer $i gehört $startnummern[$i]\n"; } ====================================================================== Diese For-Schlaufe gibt also alle Elemente des Arrays "startnummern", mit dem dazugehörigen Index aus. Neu ist hier die $#array Variable. Diese gibt das letzte Index eines Arrays aus (hier also 5 - der Index von Majid). 2.5.5 Foreach Das ist ja schonmal ganz praktisch mit dem for und der $#-Variable. Doch gehts ned noch ein stückchen Perlischer? Kloar! Die Foreach Schlaufe, lässt einen Block für jedes Element einer Liste durchlaufen und definiert eine bestimmte Variable mit dem aktuellen Element - WAS? Naja ich zeigs euch... ====================================================================== my @startnummern = ("Peter", "Hans", "Heidi", "Ueli", "Rosa", "Majid"); foreach my $läufer (@startnummern) { print "Folgender Läufer nimmt auch Teil: $läufer\n"; } ====================================================================== Alles klar? Also foreach geht jedes Element, beginnend mit dem ersten (Index 0 - "Peter") und stopft dessen Wert in die Variable $läufer, geht die Schlaufe durch, und nimmt dann das nächste Element ("Hans") und weisst dieses zu u.s.w. Superpraktisch ist diese Form der Schlaufe für Hashes: ====================================================================== my %tiere = ( 'Pferd' => 'grau', 'Ferkel' => 'lila', 'Gorilla' => 'braun', 'Esel' => 'grau'); foreach my $schlüssel (keys(%tiere)) { print "$schlüssel hat die Farbe $tiere{$schlüssel}\n"; } ====================================================================== Der 'keys'-Operator gibt also alle keys eines Hashes zurück, was ebenfals einer Liste entspricht, die folglich in die foreach Schlaufe eingebaut werden kann. Sehr beliebt ist diese Schlaufe auch hinter dem eigenlichen Block: ====================================================================== print "$schlüssel hat die Farbe $tiere{$schlüssel}\n" foreach my $schlüssel (keys(%tiere)); ====================================================================== 2.6 Subroutinen 2.6.1 Einführung So. Wir können nun also Speichern, Ein- und Auslesen, mit unserem Script verschiedene Wege gehn und diese wiederholen lassen. Nun tun wir uns daran, uns die Arbeit einwenig zu erleichtern. Perl bietet hier unzählige möglichkeiten, die man wahrscheinlich nie alle zu Ende entdeckt hat. Eine davon, sind die Subroutinen. Sie erlauben uns, Code den wir immer wieder brauchen, auszulagern in eine zentrale Stelle und diesen dann immer und immer wieder aufzurufen. Am besten fangen wir einfach mit einem Beispiel an. ====================================================================== #!/usr/bin/perl use warnings; use strict; &nummern; # Aufruf einer explizit lokalen Subroutine &nummrn(); # Eine andere Aufrufmöglichkeit nummern(); # Noch ein anderer Aufruf (welcher mir persönlich am besten gefällt) nummern; # Fehler, kein gültiger Aufruf # Definition der subroutine "Nummern" sub nummern { for (my $i = 0; $i < 7; $i++) { print $i; } } ====================================================================== Wie man sieht, ist am Ende des Script die Subroutine "nummern" definiert. Diese kann dann, durch verschiedene Wege aufgerufen werden. Der Aufruf funktioniert im Prinzip so, dass der Code der Subroutine genommen wird, und an die Stelle des Aufrufs gepackt wird. Es gibt wie gezeigt auch verschiedene Wege die Subroutine aufzurufen. &nummern; bzw &nummern(); ruft eine Routine im aktuellen Paket auf (also in der aktuellen Datei). Wird diese nicht gefunden, pisst euch Perl ans Bein und gibt einen Fehler aus. Der Aufruf nummern() ruft die Funktion nummern() auf. Gibt es bereits eine Eingebaute Perlfuntion die denselben Namen trägt, so wird diese bevorzugt. Will man also eine Perlfunktion wie z.B. "keys" überschreiben, definiert man eine Subroutine mit demselben Namen und muss diese dann mit &keys aufrufen. 2.6.2 Argumente Da Variabeln nur im aktuellen Block gültig sind, aber man einer Routine vielleicht auch mal einen Wert übergeben will (die Subroutine befindet sich ja ausserhalb des Blocks, indem my Variablen gültig sind), kann man dieses im Aufruf machen. ====================================================================== nummern(2, 6); # Aufrufen der Sub. Es werden zwei Werte übergeben. # Definition der Subroutine "nummern" sub nummern { my $startnummer = $_[0]; my $endnummer = $_[1]; for (my $i = $startnummer; $i <= $endnummer; $i++) { print $i; } } ====================================================================== Wie man vielleicht schon entdeckt hat, werden übergebene Werte in der Subroutine im Array @_ abgelegt. Somit hat bei unserem Beispiel die Variable $_[0] den Wert 2, welcher beim Aufruf übergeben wurde. $_[1] hat den Wert 6. Doch Perl wäre nicht Perl, wenn das noch ein Stückchen cooler ginge: ====================================================================== sub nummern { my $startnummer = shift; my $endnummer = shift; ====================================================================== So. Den shift Operator kennen wir ja bereits aus Kapitel 2.2.2 Arrays. Zur Wiederholung: er schnibbelt das erste Element eines Arrays ab, und gibt es zurück. Doch das besondere an shift ist, dass wenn kein Array angegeben wurde (und es in einer Subroutine aufgerufen wird), auomatisch das Array @_ als Argument genommen wird - also die über- gebenen Argumente an die Subroutine. Da das erste Element abgetrennt wird, wird automatisch das nächste zum ersten - somit, reicht es, einfach mehrmals shift aufzurufen. 2.7 Module So. Da wir nun die Basis von Perl mehr oder minder beherrschen, kommt nun der Teil, andems so richtig abgeht. Die Perl Community hat in den letzten Jahren ein gigantischs Modularchiv aufgebaut, welches über www.cpan.org zu erreichen ist. Hier gibt es wirklich für alle Module. Excel, Datenbanken, Filesystems, Bildbearbeitung, Brainf*ck, Dokumentation, ... diese Liste könnte weit, weit fortgeführt werden. Doch was sind Module eigentlich? Nun, nemhen wir an, ich habe eine Coole Subroutine geschrieben, und will diese aber nicht nur in einem, sondern auch in anderen Scripts benutzen. Ein Weg wäre, die Subroutine zu kopieren, oder vom einten auf das andere Script zuzugreiffen. Doch es gibt etwas besseres - die Module. Ein Modul ist nichts weiter, als eine kleine (oder etwas grössere ;) ) Ansammlung von Subroutinen die für irgendetwas zuständig sind. Diese können dann von den Scripts aufgerufen und eingebunden werden. Dieses einbinden funktioniert mit "use". Achso :) Jap... strict und warnings sind ebenfals Module. Vielleicht ein kleines Beispiel um zu zeigen, wie einfach man mit machen Modulen, grosses erreichen kann. ====================================================================== #!/usr/bin/perl use warnings; use strict; use LWP::Simple; # Einbinden des LWP::Simple Moduls, dass dafür zustänmdig ist, HTTP Seiten zu übertragen my $gcfseite = get("http://www.gcf.de"); print $gcfseite; ====================================================================== So. Nun, was dieses Script tut, ist wohl allen klar ;) Es ruft die gcf.de Seite ab, und gibt sie nach STDOUT aus. Was wir hier sehen, ist das Benutzen der Subroutine "get" vom Modul LWP::Simple. LWP::Simple ist Standard auf Active- States Perl-Distribrution und kann auch ohne Probleme auf Linux-Systemen über CPAN installiert werden. Doch wie sieht nun diese "get" Routine aus? Schauen wir sie doch einfach mal an... Unter Windows und ActivePerl gehen wir in das Verzeichnis Perl\site\lib\LWP und siehe da: Simple.pm Nun einfach mit dem Texteditor öffnen und mal einwenig darin herumstöbern. Wenn wir etwas herunterscrollen finden wir sie. Die Subroutine get: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ sub get ($) { %loop_check = (); goto \&_get; } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Nun, diese hier tut nicht gerade viel. Sie leitet im Prinzip die Anfrage in die Subroutine _get um. Doch was da genau passiert, muss uns auch nicht interessieren. Aber vielleicht hat man jetzt verstanden, wie das mit den Modulen funktioniert. Jedes Modul auf CPAN hat eine Dokumentation. Am Anfang ist diese vielleicht noch schwer verständlich, doch je länger man mit Perl arbeitet, dessto besser versteht man die Dokus und dessto einfacher kann man Module einsetzen. Und dann fängt es an spassig zu werden. Hier die Dokumentation zur Funktion get: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ get($url) The get() function will fetch the document identified by the given URL and return it. It returns undef if it fails. The $url argument can be either a simple string or a reference to a URI object. You will not be able to examine the response code or response headers (like 'Content-Type') when you are accessing the web using this function. If you need that information you should use the full OO interface (see the LWP::UserAgent manpage). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2.8 Referenzen 2.8.1 Grundlagen Perl ist, wie viele andere Programmiersprahcen, von seinen Variabletypen sehr linear aufgebaut. Doch was ist nun, wenn wir nicht nur eine einfache Liste, sondern eine Liste mit mehreren Elementen, welche wiederum Elemente haben, darstellen wollen? Wir können für eine kleine Tabelle für die Eigenschaften von Max, Moriz, Fix und Foxi einfach 4 Arrays bauen: ---------------------------------------------------------------------- # Name Augenf. Alter Haarfarbe my @max = ("Blau", 14, "Blond"); my @moriz = ("Blau", 13, "Braun"); my @fix = ("Schwarz", 3, "Rot"); my @foxy = ("Braun", 3.1, "Ror"); ---------------------------------------------------------------------- Über diesen Weg haben wir also eine Tabelle, mit 4 Zeilen und 3 Spalten gebaut. Doch ist diese Art von Tabellener- stellung ziemlich mühsam. Geht das nicht einfacher, und vorallem, ohne für jede Zeile einen Namen zu verbrauchen? Klar! Über ein anonymes Array. Doch dazu mehr in 2.8.2 Array von Arrays. Doch war bewirkt nun eigentlich eine Referenz? Eine Referenz muss man sich als einen Zeiger vorstellen. Jede Variable in Perl hat einen Speicherbereich und einen Namen. Der Name ist eine Referenz auf den Speicherbereich, der zum Namen gehört. Wenn ich also die Variable $hans aufrufe, schaut mir Perl in einer Tabelle nach, in welchem Speicherblock sich die gewünschen Informationen befinden. Eine kleine ASCII-Grafik zur Veranschaulichung. +----------+ +-----+-------------+--------+----------+------+ | $hans |------------>| | | | | | Speicher | @array |----- +-----+-------------+--------+----------+------+ | $blu | \ ^ ^ ^ +----------+ ------------------[0]----------[1]-------[2] Im Prinzip sind nun diese Pfeile die (harten) Referenzen. Was wir nun machen können, ist eine neue Referenz auf denselben Speicherbereich legen, wie er von einer Variable schon benutzt wird. Also im Prinzip einfach einen neuen Weg, über den die selbe Variable aufgerufen werden kann. 2.8.1 Skalare Referenz Jede Referenz, egal ob auf ein Skalar, ein Array oder ein Hash, ist eine Skalare Referenz. Referenzen werden mit dem \ Operator geschaffen. Ein Beispiel: ---------------------------------------------------------------------- $hans = "Peter"; $ref = \$hans; ---------------------------------------------------------------------- Hier wird eine Skalare Referenz zum Wert "Peter" aufgebaut. Man kann nun diesen Wert entweder über $hans oder über $ref aufrufen. Wenn der Wert verändert wird, ist der neue Wert über beide Wege zu erreichen. Der Wert wird also wie gesagt nicht kopiert, sondern nur nochmal verwiesen. Das nennt man eine harte Referenz. Eine Andere Art der Referenz ist die weiche Referenz. Eine weiche Referenz zeigt nicht auf den Wert, sondern auf den Namen der Variable. Somit ist also der Pfeil nicht auf den Speicher gerichtet, sondern auf die Tabelle mit den Namen, welche wiederum die Pfeile auf den Speicherbereich beinhaltet. ---------------------------------------------------------------------- $hans = "Peter" $ref = "hans"; ---------------------------------------------------------------------- Der Wert "Peter" wird nun über den Namen der Variable aufgerufen: $$ref gibt den wert "Peter" zurück. Hier wird erst die innere Variable aufgelöst: Der Wert von "$ref" ist also "hans" -> $hans Dann wird in der Namenstabelle nach der Variable mit dem Namen hans gesucht, welcher dann also den gewünschen Wert zurückgibt. Die Harte Referenz wird wesentlich öfter verwendet, und es ist auch die einzige Referenzart, die unter "use strict 'refs'" nicht zu einem Fehler führt. 2.8.2 Arrays von Arrays Es ist auch möglich, namenlose Referenzen zu erzeugen. Dies brauchen wir, um mehrdimensionale Arrays herzustellen. Wir erstellen also ein Array von Referenzen auf Arrays: ---------------------------------------------------------------------- my @max = ("Blau", 14, "Blond"); my @moriz = ("Blau", 13, "Braun"); my @fix = ("Schwarz", 3, "Rot"); my @foxy = ("Braun", 3.1, "Roter"); my $namen = (\@max, \@moriz, \@fix, \@foxy); # Wir erstellen eine Liste aus Anonymen Arrays print $namen->[0]->[2]; # Array 0 -> max, Wert 2 -> Blond my $anonym_ref = [["Blau", 14, "Blond"],["Blau", 13, "Braun"],["Schwarz", 3, "Rot"]]; # Erstellen einer Liste von Arrayreferenzen, ohne diese vorher zu definieren. $anonym_ref->[0]->[2] = "Braun"; ---------------------------------------------------------------------- In diesem Beispiel hier, kreiieren wir also eine Zweidimensionale Tabelle. Es sind auch drei-, vier-, fünf-, auch n- Dimensionale Arrays möglich. Also ein Array zu Arrayrefenzen zu Arrayrefeenzen (zu Arrayrefeenzen, zu...). Der -> Zeiger ist hier Speziell. Dieser wandelt eine Referenz gleich in das eigentliche Array um. Es ist also nicht mö- glich das 5. Element des 2. Elements so anzuzeigen: $array[2][5]. Wenn @array ein reell exisitierendes Array mit dem Namen "array" wäre, ginge das. Aber hier ist $array->[2]->[5] eindeutig vorzuziehen. 3. Lösungen - 2.2.1.a Die Ausgabe sieht folgendesmassen aus: ---------------------------------------------------------------------- Perl ist toll \n57 ---------------------------------------------------------------------- Das \n wird als Text ausgegeben und nicht als Newline, da bei der Definition my $text2 = 'oll \n'; einfache Anführungszeichen benutzt wurden, welche _nicht_ Interpoliert werden. Wären doppelte Anführungszeichen benutzt worden, gäbe es zwischen dem Text und der Zahl ein Newline. - 2.2.2.a Eine Möglichkeit (unter tausenden) wäre diese: ====================================================================== my @array = ("P", "e", "r", "l", "i", "s", "t", "o", "l", "l"); my @temp_array = (pop(@array), pop(@array), pop(@array)); push (@array, "t", reverse @temp_array); ====================================================================== Hier werden die letzten 3 Elemente in verkehrter Reihenfolge weggepopt. @temp_array sieht dann so aus: ("l", "l", "o"). Dann drücken wir ein "t" und das verkehrte @temp_array wieder in @array. Wir müssen das Array umdrehen, da beim pop ja immer das letzte Element entfernt wurde. Somit wird beim ersten Pop, das letzte Element übergeben, welches dann zum ersten Wert von @temp_array wird. Mit reverse drehen wir es wieder richtig. - 2.2.3.a ====================================================================== $hash{1} = 'Wasser'; $hash{2} = 'fall'; $hash2{$hash{1}.$hash{2}} = 'schön'; $hash2{$hash2{$hash{1}.$hash{2}}} = 'gut'; ====================================================================== Der Witz des ganzen hier ist der, dass Schlüsselnamen nicht nur als fester String angegeben werden können, sondern auch als Variabelnamen. $hash{1}.$hash{2} verknüpft die zwei %hash Elemente zu: 'Wasserfall', was dann schlussendlich dazu führt, dass %hash2 ein Element 'Wasserfall' mit dem Wert 'schön' beinhaltet. In der nächsten Zeile wird dann der Wert von %hash2's 'Wasserfall' (also 'schön') zum neuen Namen eines Keys mit Wert 'gut'. Somit hat %hash2 zwei Elemente: 'Wasserfall' => 'schön' und 'schön' => 'gut' - 2.3.1.a ===================================================================== #!/usr/bin/perl use warnings; use strict; print "Wie heisst du? "; chomp(my $name=); print "Hallo, $name\n"; ===================================================================== - 2.5.2.a Eine mögliche Methode: ===================================================================== #!/usr/bin/perl use warnings; use strict; my $zahlenraum = 100; # Bestimme den Zahlenraum der benutzt werden soll. my $zahl = int(rand($zahlenraum) + 1); # Definiere die Zufallszahl. Int runtet auf ganze Zahlen ab, rand gibt eine # Zahl zwischen 0 und dem Argument zurück, wesshalb noch 1 addiert werden muss my $zaehler = 0; # Den Zähler für die Versuche auf 0 stellen print "Herzlich Willkommen beim Zahlenraten. Du musst nun eine Zahl zwischen 1 und $zahlenraum herausfinden.\n\n"; my $eingabe; # Da "while" eine Abfrage macht, muss $eingabe auch ausserhalb der Schlaufe gültig sein. do { ++$zaehler; print "$zaehler. Tipp: "; chomp($eingabe = ); if ($eingabe == $zahl) { print "Richtig!\n"; } elsif ($eingabe < $zahl) { print "Die gesuchte Zahl ist grösser\n"; } else { print "Die gesuchte Zahl ist kleiner\n"; } } while ($eingabe != $zahl); print "Herzlichen Glückwunsch. Du hast $zaehler Versuche gebraucht um die Zahl zu finden.\n"; ===================================================================== 4. Nachwort So das wars erstmal von meiner Seite. Die Grundlagen der Perlprogrammierung sollten nun einigermassen klar sein. Wenn ihr Lust habt, mal einen Blick in eines meiner Perl Projekte zu werfen, an einem Mitzuarbeiten oder ob ihr Hilfe bei einem eurer Scripte benötigt, seid so frei und schreibt mir oder schreibt einfach ins GCF-Board. Dämnächst wird wohl eine Abhandlung über CGI folgen. Und wenn das ganze gut ankommt, überwind ich mich vielleicht auch mal ein Tutorial zu regulären Ausdrücken und der objektorientierten Programmierung zu schreiben *g* Bis dahin... Viel Spass mit Perl ;) 4.1 Kontakt So. Falls etwas ned verständlich war, oder falls ihr sonnst irgendwas loswerden wollt: Schreibt mir ;) Mail: Thorium@gcf.de IRC: IRCnet als Darkwell oder EuIRC in #perl 4.2 Weiterführende Literatur Titel: Programmieren mit Perl von O'REILLY ISBN: 3-89721-144-0 Preis: EUR 56.- 4.3 Sonnstige Links http://www.gcf.de ;) http://www.gcf-board.de http://www.perl.de Deutschsprachiges Perl-Forum (sehr zu empfehlen für alle komplexeren Fragen) http://www.perlmonks.org http://www.activestate.com Perl-Interpreter für Windows (auch Phyton & andere Interpreter und Tools) http://www.perldoc.org Perl-Dokumentation http://www.cpan.org Das wohl grösste Modulverzeichnis für Perl http://selfhtml.teamone.de Sollte jeder kennen 4.4 Dank an - Die perl.de Community - Meine Freundin, die mich nie Tutorials schreiben lässt *knuddel* - Der Musik. Besonders: "Lacuna Coil", "Katatonia", "Samsas Traum", "Duivelspack", "Horch" und "Rabenschrey"