Perl v5.0 Referenz
(wenn das Buch fehlt)
Inhalt: Allgemeines, Scalare, Listen, Hashes, Bedingungen, Schleifen, anonyme Variablen, regular Expressions, Funktionen, Dateien & Pipes, Packages, Klassen, Tips & Tricks, Debugging, Aussergewöhnliches, der Autor dieser Kurzreferenz...


Allgemeines:

Operatoren:

Beispiel: Erklärung:
print 1 + 1; Addition
print 3 - 2; Subtraktion
print 2 * 2; Multiplikation
print 1 / 2; Division
print 3 % 2; Modulo
print 2 ** 3; Exponent
print 2 < 3; ? kleiner als
print 2 <= 3; ? kleiner gleich
print 2 > 3; ? größer als
print 2 == 3; Zahlenvergleich
print 2 != 3; nicht(Zahlenvergleich)
print 2 <= 3 && 3<=4; && = logische Undverknüpfung
print 4 << 2; Bitverschiebung links
print 4 >> 2; Bitverschiebung rechts
print 4 & 0x01; bitweises Und
print 4 | 0x01; bitweises Oder
print 4 ^ 0x01; Bit-Exclusiv-ODER
$c = $a > $b ? $a : $b; Ternärer Vergleichsoperator
$test++; Increment
$test--; Decrement
print "Hallo" . "Welt" . "\n"; Stringzusammenfügen
print "Hallo" x 2; Stringwiederholung
$_ =~ /Muster/; String passt
$_ !~ /Muster/; String passt nicht
print "Harry" eq "Herbert"; [eq lt gt ge] Vergleichsoperatoren für Strings (Scalare)
print "Harry" cmp "Otto"; noch ein Vergleichsoperator
print ~34; Bitkomplement

Unter Unix sollte die erste Zeile in einem Script ungefähr so aussehen:
#!/usr/bin/perl
die aktuelle Shell (meist bash) liest diese Zeile und führt das Script mit dem perl-Programm aus, das in /usr/bin liegt. Wer nicht genau weiss wo perl auf seinem System liegt kann meist mit
which perl
nachfragen!




Alles über Scalare (bessere Strings):

$test = 3; # Scalar anlegen
$test2 = "Hallo ich bin ein Skalar " . $test; #neuen scalar anlegen und einen dranfügen.
print ("in Skalar test2 steht: $test2 drin"); # ausgabe
print ('in Skalar $test2 steht ',$test2,' drinn'); # in '' stehende Strings werden nicht
                                                   # ausgewertet.

Referenzen:

$testref = \$test; # eine Referenz von $test wird in $testref angelegt
$deref = $$testref; # in deref steht wieder der Inhalt von $test...
$deref = ${$testref}; # dasselbe

Weitere Funktionen mit Strings:

if (defined $a) { print ("Ja - ist definiert") }; # no comment...
chop($test); # das letzte Zeichen aus $test wird herausgeschnitten und zurückgeliefert
chomp($test); # das abschliessende Newline-Zeichen wird entfernt
              # und ggf. die Anzahl der abgeschnittenen Zeichen zurückgeliefert
$length = length($test); # no comment
$partstr = substr($string,$offset,$length); # $partstring ist der teil des $string, der ab
                                            # $offset anfängt und die Länge $length hat...

Besondere Scalare:

$_ "default" Scalar
$~ Format-Scalar
$| !=0 : jedes Zeichen wird sofort ausgegeben; sonst nur bei \n

Besondere Zeichen:
 
\n Neue Zeile
\r <ENTER> - Taste
\t Tabulatorschritt
\f Seitenvorschub
\b <delete> - Taste
\v Zeilenvorschub
\a Alarm
\e <Esc>-Taste
\0x Oktal-Wert in x
\Xx Hexadezimalwert in x
\cx <STRG>+<X>
\\ das - \ - Zeichen
\l das nächste Zeichen in Kleinschreibung
\L Alle Zeichen bis zum nächsten \E in Kleinschreibung
\u Das nächste Zeichen in Grosschreibung
\U Alles Zeichen als Grossbuchstaben bis zum nächsten \E
\E begrenzt \L und \U



Listen:

@liste = ("Erstes Element", "zweites", $test, 42); #definiert eine Liste, oder
@liste = qw(ErstesElement zweites $test 42); #Leerzeichen gliedert Liste
$element = $liste[2]; #ein Element in einen Scalar kopieren
@part = @liste[3,4,7,10]; # Teil einer Liste in eine andere Liste
@part = @liste[3..7]; # einen anderen Teil...
($eins, $zwei) = (1 , 2, 3, 4); # Zuweisung - überflüssiges (3,4) wird weggeschmissen
                                # zu viele Werte im lvalue bekommen ggf. den Wert undef
print ($#part); #Anzahl der Elemente in @part-1

Listen und Strings:

Besondere Listen:
$ARGV Parameter die dem Script übergeben wurden

$string = join("\n", @list); #die Einträge in @list werden durch "\n" - getrennt
                             # in $string übergeben...

Mehrdimensionale Listen:

$field[4][7] = 13; # Zweidimensionales Feld
$space[2][3][1] = "Wert"; # Dreidimensionales Feld

Funktionen mit Listen:

push (@alist, $scalar); # fügt $scalar ans Ende der Liste ein
$element = pop (@alist); # entfernt das letzte Element der Liste und liefert es zurück
unshift(@alist,$scalar); # fügt $scalar an den Anfagn der Liste ein
$element = shift(@alist); # entfernt das erste Element der Liste und liefert es zurück
splice(@alist,$offset,$length,@insertlist); # ersetze die Teilliste von @alist, die
                          # beim $offset beginnt und $length Elemente
                          # lang ist, durch die Liste @insertlist
grep { Funktionsblock } @list; # Evalutiert den Funktionsblock für
                               # jedes Listenelement und reiht es
                               # in die Ergebnissliste ein, falls
                               # der Rückgabewert wahr ist
grep EXPR, @list ; # Wie oben, nur evaluiert der Aufruf
                   # den ausdruck EXPR
map { Funktionsblock } @ list; # Evaluiert den Funktionsblock für
                               # jedes Listenelement und steckt den Rückgabewert
                               # in die Ergebnisliste
map EXPR, @list; # Wie oben nur mit EXPR

(Anmerkung: Es funktioniert auch Pattern Matching. @part=grep /e/, @list; )

Referenzen:

$arrayref = \@array; # referenz eines Arrays

@array = @$arrayref; # ursprungsarray
@array = @{$arrayref}; # oder so..

$element = ${$arrayref}[2]; # element aus einer referenz
$element = $arrayref->[2]; # oder so..



Hashes: (soggn.: assoziative Arrays)

$value = $myhash{"name"}; # Hashes verknüpfen Scalare mit anderen Scalaren. Hier
                          # wird der wert zurückgegeben mit dem "name"
                          # verknüpft wurde
$myhash{"name"}="Christopher"; # hier wird "name" -> "Christopher" zugewiesen

%myhash ist der Bezeichner von dem Hash
mit keys %myhash extrahiert man sämtliche Keys des Hashes
mit values alle Werte... (siehe Schleifen..)

if (exists($myhash{"name"})) { ... } # stellt fest ob der Key existiert...
delete($myhash{"name"}); # löscht den Key - "name" ...
%hash = ("key1" => "val1", "key2" => "val2", ...); # Initialisiert einen Hash

print "Hashinalt: @{[%hash]} \n"; # gibt den hashinhalt durch Leerzeichen
                                  # getrennt aus..

Referenzen:

$hashref = \%hash; # Hash -> Hashreferenz

%hash = %$hashref; # Hashreferenz -> Hash
%hash = %{$hashref}; # dasselbe

$value = ${$hashref}{"key"}; # Hashreferenz -> value
$value = $hashref->{"key"}; # dasselbe



Bedingungen:

if ($a =~ /p/) { ... } # die wohl typischte Bedingung mit einem Pattern (p)
if ($a ==42 ) { ... } elsif ($a <42) { .. } else { .. }
# jeder dann ausgeführte Code muss in geschweifte Klammern
$a =~ /p/ && do { .. }; # if fuer ein regular Pattern...
$max = $a > $b ? $a : $b; # $max = maximum($a, $b);
print "$file ist keine Datei\n" unless -f $file;



Schleifen:

.. über Listen:
for (@list) { print $_; } # für jedes Listenelement fülle $_ und schreibs raus...
oder:
foreach $i (@list) { print $i; } # nicht den Standardscalar, sondern $i
oder
for ($i=0; i<=$#list; $i++)
{ print $list[$i]; } # die c/c++ - Methode ;)

Schleifenkontrolle:
innerhalb der Schleife stehende Ausdrücke..

next; # mache sofort mit der nächsten "Runde" weiter...
last; # breche jetzt ab und erkläre die Schleife für beendet
redo; # mache diesen Schleifendurchlauf nochmal

Schleifen über Hashes:
foreach $key (keys %testhatch) { ... } # über Keys interieren
while (($key, $value) = each %testhash) { .. } # das gleiche nur als Paar



Anonyme Variablen:

[1, "zwei", 3] # erzeugt anonyme Liste
{ "key1" => "value1", "key2" => "value2" } # anonymer Hast
@{[func()]} # ein Cast des Ergebnisses der Funktion zu Liste
$funcref = sub { ... }; # anonyme funktion
$scalaref = \42; # "anonymer scalar"...

@{...} ist also ein Listencast...



reguläre Ausdrücke:

$string =~ /PATTERN/; #liefert true wenn PATTERN in $string vorkommt
if ($string =~ /Bill/) {
  print "Bill in string!\n";
}

Sonderzeichen im Pattern:
\s \S Whitespace (Leerzeichen) / Kein Whitespace
\w \W Alphanumerisches Zeichen /Nicht alphanumerisch
\d \D Ziffer / Keine Ziffer
\b \B Wortgrenze / Keine Wortgrenze


[1234] [1-4] Menge als Aufzählung / Bereich
[^567] [^5-7] Ausgeschlossene Mengen
. Beliebiges Zeichen (außer Newline)

Quantifikatoren für vorhergehendes Pattern:
* Keinmal oder beliebig oft
? Keinmal oder einmal
+ Einmal oder beliebig oft
{m} Genau m-mal
{m,} Mindestens m-mal
{m,n} m-mal bis n-mal

\1, \2, ... Rückwärtsreferenz
(...) Gruppierung
(?:...) Gruppierung ohne Rückwärtsreferenz
^ Zeilenanfang
$ Zeilenende
a|b|c Alternativen
*? +? ?? {...}? Non-greedy-Operator (Minimalmatch)
(?=...) (?!...) Lock-Ahead positiv/negativ

Ausmaskieren von Metazeichen:

$string = 'Dollar($) Backslash (\)';
print quotemeta($string);

Besondere Modifikatoren für reguläre Ausdrücke:

Nach dem abschliessenden / in einem regulären Ausdruck können noch (ein oder mehrere) Modifikatoren stehen:
/.../m Multiline - Wenn der String mehrere Zeilenumbrüche enthält wird jede Zeile separat von der Suche behandelt bis sie Erfolg hat.
/.../o Jede Variable wird nur ein mal interpretiert - eventuell aus diesem Inhalt entstehende weiteren Variablen werden nicht behandelt
/.../s Singleline - Der Suchstring wird als Einzeiler interpretiert
/.../i Gross/Kleinschreibung ignorieren

Ergebnissvariablen nach erfolgreichem Pattern-vergleich:

$' oder $POSTMATCH Enthält alles des Strings was nach dem Match lag (super interessant für rekursive Suchen)
$& oder $MATCH Enthält den Stringteil der zum erfolgreichen Match führte
$` oder $PREMATCH Enthält alles des Strings was vor dem Match lag
$<Ziffer> also $1 oder $2 oder ...

Enthält die gefundenen Teile die beim Pattern-vergleich in Klammern standen.
if ($test =~ /(hallo)[\s]+(du)/) {
  print $1; # wird "hallo" sein
  print $2; # wird "du" sein
}

Suchen und Ersetzen:

$test =~ s/suche/ersetze/g;

s/^([^ ]*) *([^ ]*)/$2 $1/; # vertauscht die ersten beiden Wörter



Funktionen: (& was man damit machen kann)
Deklaration:

sub meinname # deklaration einer funktion
{..}
Aufruf ohne Parameter:
func(); # oder
&func; # oder
&func(); # ...
Aufruf mit Parameter:
func($par1, $par2); # oder
&func($par1, $par2); # oder
func $par1, par2;

Die Werte der übergebenen Parameter stehen in dem Array @_ und können am cleversten mit my $var1 = shift; geholt werden.
return xx; gibt einen Wert zurück, ansonsten wird der Wert genommen, der zum Schluss in $_ oder @_ stand.
der
my - Operator begrenzt den Gültigkeitsbereich einer Variablen lokal.

@mylist = @{[func()]}; # erzwingt Array-Kontext für Funktion func();

Referenzen:

$funcref = \&func; # Function -> Funktionsreferenz
&$funcref;   # Funktionsreferenz -> Aufruf
&$funcref(); # dasselbe



Dateienzugriff & Pipes:

Tests:
open (FILE, ">file") || die("Cannot open $file!");  # test...

Datei Operatoren:
-r -R Effektive/Reale UID+GID hat Leserechte
-w -W Effektive/Reale UID+GID hat Schreibrechte
-x -X Effektive/Reale UID+GID hat Ausführungsrechte
-o -O Effektive/Reale UID+GID ist Eigentümer
-e -z Existiert / hat Größe Null
-s Größer als 0 Bytes (gibt Größe zurück)
-f -d -l Typ: Datei / Verzeichnis / Symbolischer Link
-S -p Socket / Named Pipe
-b -c Block / char Device
-u -g -k Setuid / Setgid / Sticky-Bit gesetzt
-t Ist ein tty
-T -B Text / Binärdatei
-M -C Gibt Tage seit der letzten Modifikation / Rechteänderung zurück

Öffnen allgemein:

open (INFH, "<file.dat"); # Lesender Zugriff
open (OUTFH, ">file.dat"); # Schreibend und ggf. neu anlegen
open (OUTFH, ">>file.dat"); # Schreibend und ggf. anhängen

- STDIN, STDOUT, STDERR # Standardhandles
- <> # STDIN oder Dateien auf der Kommandozeile

while  (<INFH>) { print $_; } # oder
@infh = <INFH>; while (@infh) { print $_; }

Pipes:

open (LS, "/bin/ls |"; # Pipe lesend öffnen
open (PRINTOUT,"| /bin/lp"); # Pipe schreibend öffnen

open (PRG,"programm 2>&1 |"); # Veranlasst
     # zumindestens unter Linux STDERR und STDOUT zusammengefasst
     # zu lesen....
 
Ausgabe:

print INFH "Text\n";

Directorys:

opendir(DIR,"/usr/bin");
@entries = readdir(DIR);
closedir(DIR);



Packages:
so eine Art Libraries in Perl. Das Standart-Packet scheint CORE zu sein. Aus einem speziellen Packet ruft man beispielsweise durch:

CORE::print("Howdy, World!\n");
auf...

package test; # definiert den nächsten Teil als Package namens "test"
use Test; # includiert Test...



Klassen:
zu Klassen will ich derzeit nur sagen, das die Funktion bless();  eine Referenz zurückgibt, die quasi als this-Pointer den Namensraum der derzeitigen Funktion definiert.
Eine typische Perl-Klasse sieht ungefähr so aus:

package Packet_mit_Klassen;
  sub new {
    bless{}; # baut einen neuen Namensraum für ein neues Objekt
  }
  sub eine_funktion {
    my self$ = shift; # es ist so Konvention, das als Parameter der eigene Namens-
                      # raum mitgeliefert wir
    ... # tuwas
  }
package main;
use Packet_mit_Klassen;
  $objref = Packet_mit_Klassen->new();
  $objref = Packet_mit_Klassen->eine_funktion(); # die Funktion dieser Klasse wird
                                                 # angesprungen...



Tips & Tricks:
1. Strengere Variablenkonventionen

   use strict;
   globale Variablen dürfen nur noch in der Form $Package::var vorliegen; (damit der my-Obperator nicht vergessen wird..)

2. Umgang mit der Zeit
  $zeit = time(); #zeit in secs
 $zeit2 = scalar localtime(); #echte zeit
  Dadurch wird einmal die Zeit in Sekunden (zum Rechnen) angegeben, einmal mit Wochenangabe
  und formatiert...



Der Debugger:
Perl hat einen integrierten Source-Debugger.
start mit:
perl -d script

Kommandos des Terminals:
Kommando: Bedeutung:
T Stack beobachten
s Einzelschritt
n Nächster Schritt, übergeht Subroutinenaufrufe
r Rückkehr von der aktuellen Subroutine
c  [line] Fortführung; optionales Einsetzen eines Einmal-Stoppunktes an der gewünschten Zeile
<CR> Wiederholt den letzten n- oder s-Befehl
l min+incr Listet incr+1 Zeilen, beginnend von min.
l min-max Listet Zeilen auf
l line Zeigt Zeile an
l Zeigt nächste Seite
- Zeigt vorhergehende Seite
w line Zeigt Seite um die Zeile herum
l subname Zeigt Subroutine
f filename Wechselt zum Dateinamen.
/pattern/ Sucht vorwärts nach Mustern; das abschliessende / ist optional
?pattern? Sucht rückwärtz nach Mustern
L zeigt Stoppunkte und Aktionen
S Listet die namen der Subroutinen auf
t Wechselt zum Trace-Modus
b [line] [condition] Setzt Stoppunkt; Zeile wird zur aktuellen Ausführungszeile; der Zustand wechselt, wenn er ein Wahr erkennt, Voreinstellung auf 1.
b subname [condition] Setzt Stoppunkt an der ersten Zeile einer Subroutine
d [line] Löscht Stoppunkt
D Löscht alle Stoppunkte
a [line] command Setze eine Aktion auf getan, bevor die Zeile ausgeführt wird. Die Filge ist: Prüfung auf Stoppunkt, druckt die Zeile wenn nötig, führt Aktion aus, und teilt dem Benutzer einen Stoppunkt oder Schritt der Zeile mit.
A Löscht alle Aktionen
V [pkg [vars]] Listet einige (Voreinstellung: alle) Variablen auf (Voreinstellung: aktuelle)
X [vars] Dasselbe wie >V currentpackage [vars]<.
< command Definieren des Befehls vor der Meldung
> command Definieren des Befehls nach der Meldung
! number Wiederholung des Befehls (Voreinstellung: vorhergehender Befehl)
! - number Wiederholt bestimmte Anzahl letzer Befehle
H -number Zeigt letzte Anzahl der Befehle (Voreinstellung: alle)
q or ^D Beenden
p expr Dasselbe wie >print DB<<OUT expr< im autiellen Paket
= [alias value] Definiert einen Befehls-Alias, oder listet alle aktuellen Aliase auf
command führt einen Befehl als perl-Statement im aktuellen Packet aus.

aussergewöhnliche Funktionen in Perl:



Formatierungsbefehle:
Beispiel:

format NAME =
+----------------------------------+
|                                  |
| @<<<<<<<<<<<<<< @<<<<<<<<<<<<<<  |
$vorname, $nachname
|                                  |
| @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  |
$strasse
| @<<<<< @<<<<<<<<<<<<<<<<<<<<<<<  |
$plz, $ort
|                                  |
+----------------------------------+
.
legt ein Format an. Abgeschlossen durch einen Punkt, der als erstes und einziges Zeichen in der letzen Zeile steht.
Ein Formatierstring beginnt mit einem @-Zeichen, dann folgen Formatierzeichen:

 
Zeichen Bedeutung
< Linksbündiger Text
> Rechtsbündiger Text
| Zentrierter Text
# Numerisches Feld
* Mehrzeiliges Feld

für eine Kommazahl z.B.: @###.##
Statt des @-Zeichens kann auch das ^-Zeichen benutzt werden, dann steht in der zum Formatierfeld zugehörigen Variable der Rest des Textes, der evtl aus Platzgründen nicht mehr ausgegeben werden konnte...
Mit dem Tilde-Operator (~) kann verhindert werden, das für eine leere Variable eine Formatierung berücksichtigt wird.


format FLTEXT =
~^<<<<<<<<<<<<<
$textzeile
~^<<<<<<<<<<<<<
$textzeile
~^<<<<<<<<<<<<<
$textzeile
~^<<<<<<<<<<<<<
$textzeile
.
gibt einen Fließtext aus. Zwei Tilden hintereinander bedeuten, das das nachfolgende Feld so oft benutzt wird bis es leer ist.
Statt des oberen Beispiels also:

format FLTEXT =
~~^<<<<<<<<<<<<<
$textzeile
.
Perl erkennt bei den Formatierungen Wortgrenzen und bricht um.
(Perl kann so auch Seiten behandeln. Mit
$= definiert man eine Seitenlänge, $% ist die aktuelle Seitennummer. Ein Kopfformat besteht aus dem Formatnamen und einem angehängten _TOP.)

Zwei Möglichkeiten zum Benutzen der Formate:
format STDOUT=
....
....
.
write STDOUT;

oder Benutzung der Variable $~ um STDOUT oder den mit select()-gewählten Dateihandle ein format zuzuweisen:
format OUT=
....
....
.
[$alt = select(DATEI);]
$~ = "OUT";
[select($alt);]
write;



HERE-Dokumente:

Der Operator << legt den Terminations-String fest, der einen beginnenden, eventuell mehrzeiligen Text abschließt:

$text = <<BriefEnde;
Lieber Anwender!

Wegen dringender Wartungsarbeiten ist derzeit kein
Zugriff auf den Server $server möglich.

Fröhliches Kopfrechnen! Ihre Systemadministratoren
BriefEnde

Im Beispiel wird $server durch den Variableninhalt ersetzt. Ist dies nicht erwünscht dann...

print <<'TheEnd';
Die Kosten betragen $100.
TheEnd

Das funktioniert übrigends fast beliebig komplex:

Foreach $i (split(/\n/,<<TextEnde)) {
Zeile1
Zeile2
TextEnde
  Print "$i\n";  # Zeile ausgeben
}



Gute Bücher zum Thema:
Effektives Programmieren mit Perl 5 / Michael Schilli / ADDISON-WESLEY Verlag / ISBN 3-8273-1095-4
Diese Kurzübersicht hat verbrochen:
Christopher Kohlert
am 18.12.2004 wurde sie etwas verbessert.