Ein einfaches Programm zur Ausgabe einer Textzeile auf dem Bildschirm
(bzw. an die Standard-Ausgabe) sieht folgendermaßen aus (unter
UNIX / AIX ) :
| #!/usr/bin/perl
# # Ausgabe einer Textzeile print "Dieser Text wird ausgegeben\n"; |
# Pfad des Perl - Interpreters # Kommentar (beg. mit #, bis Zeilenende # print - Anweisung, mit Zeilenvorschub
|
|
Anweisungen werden mit ; abgeschlossen. Leerzeilen innerhalb des Programms sind erlaubt.
Dateien müssen in Perl für die Bearbeitung geöffnet
werden:
| open ( FH , "Dateiname")
open ( FH , ">Dateiname") open ( FH , ">>Dateiname") |
# zum Lesen
# zum Schreiben (bish. Inhalt # überschreiben) # zum Fort-Schreiben ("anhängen") |
|
FH steht dabei für ein "File-Handle" (frei wählbar, Grossbuchstaben üblich), d.i. ein Datei-Bezeichner innerhalb des Perl-Scriptes.
Vordefiniert (und ohne expl. open geöffnet) sind die File-Handles
STDIN - Normaleingabe (Tastatur)Einlesen:
STDOUT - Normalausgabe (Bildschirm)
STDERR - Fehlerausgabe (Bildschirm)
$Zeile = <FH>; # Variable $Zeile erhält Inhalt der nächstenAusgeben:
# Zeile (einschl. Zeilenwechsel).
@Zeilen = <FH>; # alle - noch nicht gelesenen - Zeilen werden der Liste (array)
# @Zeilen als Werte zugewiesen.
print FH Ausgabewerte;
# Ausgabewerte werden durch Komma getrennt angegeben
# ein Zeilenwechsel ist expl. anzugeben mit "\n".
Beispiel:
open(AUS,">ausgabe.dat");
print AUS "Hallo","
Welt","\n"; # 1 Zeile mit Inhalt: Hallo Welt
print AUS "Hallo
Welt\n"; # ebenso
Bei Nutzung der Standard-Ein-/Ausgabe braucht kein File-Handle angegeben zu werden:
$z = <>; bzw. print Ausgabewerte;
NB : Für das Testen von CGI-Scripts kann / sollte man die Fehlerausgabe in eine Datei lenken, z.B. durch:
open(STDERR, ">error.dat");
In der Datei error.dat (im gleichen Verzeichnis wie das CGI-Script) werden dann Warnungen und Fehlermeldungen abgelegt.
Nach Ende der Bearbeitung wird die mit FH verbundene Datei geschlossen mit der Anweisung
close(FH);
Sie kann dann im gleichen Programm auch wieder geöffnet werden, z.B.
für eine "andere Bearbeitungsart" (etwa zunächst schreiben,
später lesen).
Am Ende des Programmablaufes werden alle noch geöffneten Dateien
automatisch geschlossen.
| Vergleich | Zahlen | Strings |
| gleich | == | eq |
| ungleich | != | ne |
| kleiner als | < | lt |
| größer als | > | gt |
| kleiner oder gleich | <= | le |
| größer oder gleich | >= | ge |
Die Verwendung unterschiedlicher Operatoren für Zahlen und Strings ist notwendig, da ja Variable keinen festgelegten Typ besitzen, sondern vielmehr ihr Inhalt gemäß dem Kontext interpretiert wird.
Beispiel: $a = 38;
$b = 7;
$a > $b # wahr
$a lt $b # wahr
falsch 0 1-1 "" "0"
wahr 1 "1" "00" "0.000"
Zusätzlich können logische Operatoren zur Verknüpfung bzw. Verneinung eingesetzt werden:
$a && $b # sind $a und $b wahr ? Genauer: $a, falls $a falsch, sonst $b
$a || $b # ist $a oder $b wahr ? Genauer: $a, falls $a wahr, sonst $b
!($a) # ist $a falsch ?
Die Auswertung einer Verknüpfung beginnt links und bricht ab, sobald eine Entscheidung gefallen ist, d.h. das Ergebnis ist der Wert von $a, wenn dieser bereits das Ergebnis unabhängig von $b festlegt ($b wird dann gar nicht ausgewertet).
Mittels logischer Verknüpfungen können an Stelle $a , $b auch Kommandos "abhängig voneinander" ausgeführt werden. Wahr bzw. falsch resultiert dabei aus der (nicht) erfolgreichen Ausführung (Return-Werte 1 bzw. 0):
cmd1 && cmd2; # cmd2 wird
nur ausgeführt, falls cmd1 erfolgreich war
cmd1 || cmd2; # scheitert cmd1,
wird cmd2 ausgeführt
Beispiel:
open (FH, "Datname") || die "kann Datei nicht öffnen\n";
| foreach $var (@liste) {
print "$var\n"; } |
# Für jedes Element der Liste werden
# die folg. Anweisungen ausgeführt # (Veränderungen von $var wirken # auf die Elemente von @liste) |
Der Anweisungsblock wird auch für undefinierte Elemente der Liste durchlaufen. Bei leerer Liste geschieht nichts.
| while (ausdruck) {
Anweisung(en) } |
# Ausführung der Anweisungen erfolgt
# so lange, wie die Auswertung von # ausdruck wahr ergibt. |
Es muss gewähleistet sein, dass ausdruck durch die Schleifen-Durchläufe
"irgendwann" den Wert falsch erhält.
Ist ausdruck "gleich zu Beginn falsch", erfolgt gar keine Ausführung.
Beispiele:
while
($z = <>) # Ausführung
für jede Zeile der Standard-Eingabe
while
($i < 100) # Ausführung, solange $i kleiner als 100
ist
Benutzt man until an Stelle von while, erfolgt die Ausführung so lange, bis ausdruck den Wert wahr erhält (keine Ausführung, wenn "gleich zu Beginn wahr").
Mit Hilfe des do - Operators kann man den while- oder until-Test an das Ende des Anweisungsblocks verlagern :
do
{
Anweisung(en)
}
while (ausdruck);
Man erzielt damit mind. eine Ausführung der Anweisung(en), weitere folgen, falls Ausdruck wahr (while) bzw. falsch (until) liefert.
| for (Anf-Wert; Bed; Inkrement) {
Anweisung(en) } |
# Anfangswert wird gesetzt, dann,
# falls Bed wahr, wird Anweisung(en) # ausgeführt, danach Inkrement. # Falls Bed wahr, erfolgt weiterer # "Durchlauf" usw. |
Beispiel:
for ($i = 1; $i < 50.5; ++$i)
{ # Schleife gibt die Zahlen 1 - 50 aus
print "$i\n";
}
Anm.: Die reservierten Worte for und foreach können für beide Strukturen eingesetzt werden (Perl weiß dann schon...).
for / foreach können auch "explizit" Listen oder Bereiche übergeben werden, um deren Elemente nacheinander abzuarbeiten :
for $i ((1,2,3,4,5)) { print "$i\n" } #
dopp.Klammern, innere zur Listen-Def.
foreach (1..5) { print "$_\n" }
# "ohne Variable" enthält $_ den
# aktuellen Listenwert
Beide Schleifen geben die Zahlen von 1 bis 5 aus.
| if (ausdruck) {
Anweisung(en)1 } else { Anweisung(en)2 } |
# ist ausdruck wahr ?
# falls ausdruck falsch
|
Es werden entweder Anweisung(en)1 (ausdruck wahr)
oder Anweisung(en)2 (ausdruck falsch) ausgeführt.
else mit folgendem Anweisungsblock kann entfallen, wenn nicht
benötigt ("asymmetrisches if"). Andererseits können auch mehr
Alternativen in die Verzweigung aufgenommen werden :
if (ausdruck1) {
# falls ausdruck1 wahr
Anweisung(en)1
} elsif (ausdruck2)
{ # falls ausdruck1 falsch und
ausdruck2 wahr
Anweisung(en)2
} else {
# falls ausdruck1 falsch und ausdruck2 falsch
Anweisung(en)3
}
Falls man "nur die else-Alternative" benötigt, kann man statt if die unless-Anweisung verwenden :
unless
(ausdruck) {
# entspricht if (!(ausdruck))
Anweisung(en)
}
Bestehen die Alternativen unter if - else aus jew. einer Anweisung / Zuweisung kann man die Verzweigung mit dem "Konditional-Operator" ? : schreiben, z.B.
$a eq $b
? print "gleich"
:
print "ungleich"; # : trennt die Alternativen
print $a eq $b ? "gleich"
:
"ungleich"; # Wirkung wie vorher
$b > $c
? $a = $b : $a
= $c;
# $a erhält den größeren der
$a = $b > $c ? $b :
$c;
# Werte von $b, $c
NB.: Diese Schreibweise trägt nicht unbedingt zur Lesbarkeit eines Programms bei.
Perl bietet die Möglichkeit, ein Hash mit einer DBM-Datenbank zu verknüpfen und dann die Bearbeitung der Datenbank "über dieses Hash" (auch DBM-Array genannt) abzuwickeln:
dbmopen (%hashname, "dbname", modus);
"öffnet" die Datenbank dbname (bzw. legt sie, falls nicht existent, mit Zugriffsrecht modus an, z.B. 0644) und "verbindet" sie mit dem assoziativen Array %hashname .
dbmclose (%hashname); # "schließt" die Datenbank
$hashname {$schl} = ausdruck; # setzt Datensatz
zu $schl auf Wert v. ausdruck
# ("überschreibt" bzw. "fügt hinzu")
delete $hashname {$schl}; # löscht Datensatz zum Index $schl
keys %hashname # Liste aller Schlüssel
values %hashname
# Liste aller Werte (=Datensatzinhalte)
Beispiel: Das folgende Programm gibt alle Sätze einer DBM-Datenbank in eine sequentielle Datei aus, aufgerufen mit
db2seq dbname > seqdateiname , falls Progamm in Datei db2seq steht.
#!/usr/bin/perl
#
# Ausgabe einer DBM-Datenbank in seq. Datei
# (DBM-Name als Aufrufparam., Std-Ausgabe
#
$file = shift;
# shift wirkt hier auf @ARGV,
# liefert ersten Aufruf-
# Parameter, also dbname
die "DB exist. nicht" unless -f "$file.dir";
# Abbruch, falls DB nicht
# existiert (geprüft
# anhand "Index-Datei")
dbmopen (%db, $file, undef);
# verbindet DB mit Hash %db
# (undef: DB wird nicht neu
# angelegt, falls nicht vorh.)
while (($schl, $wert) = each %db ) {
# alle "Hash-Element-Paare" und
# damit alle DB-Datensätze
# werden sukzessive durchlaufen
print "$schl:$wert\n";
# Ausgabeform Schlüssel:Datensatz
}
dbmclose (%db);
Die Umkehrung, d.h. Aufbau oder ggf. Erweiterung einer DBM-Datenbank aus einer sequentiellen Datei leistet:
Aufruf: seq2db dbname < seqdateiname , falls Progamm in Datei seq2db steht.
#!/usr/bin/perl
#
# Aufbau (Erweiterung) einer DBM-Datenbank aus seq.
Datei
# (DBM-Name als Aufrufparam., Std-Eingabe
#
$file = shift;
# shift wirkt hier auf @ARGV, liefert
# 1. Aufruf-Parameter, also dbname
dbmopen (%db, $file, 0644);
# verbindet DB mit Hash %db
# (0644 : DB wird ggf. mit entspr.
# Zugriffsrechten neu angelegt)
while (<>) {
# solange die Eingabe Sätze liefert
($schl, $wert) = m/^(.*?):(.*)$/;
# Satz wird am
ersten: in Schlüssel und
# Wert aufgeteilt
$db{$schl} = $wert;
# Datensatz für Schlüssel $schl wird mit
# Inhalt $wert angelegt / überschrieben
}
dbmclose (%db);
#!/usr/bin/perl
#
# Programm zum Einbringen einer seq Datei (Std-Eingabe)
# in eine BerkeleyDB-Datei (Aufruf-Parm)
#
$file = shift;
die "give db name" unless $file;
#use strict;
use DB_File;
tie %dbhash, 'DB_File', $file
or die "+++ Fehler bei Initialisierung der DB $file\n";
while(<>) {
($key, $value) = m/^(.*?):(.*)$/;
$dbhash{$key} = $value;
}
untie %dbhash;
#!/usr/bin/perl
#
# Programm zur Ausgabe einer BerkeleyDB-Datei (Aufruf-Parm)
# in eine seq. Datei (Std-Ausgabe)
#
$file = shift;
die "give db name" unless -f "$file";
#use strict;
use DB_File;
tie %dbhash, 'DB_File', $file
or die "+++ Fehler bei Anbindung der DB $file\n";
while(($key, $value) = each %dbhash) {
print "$key:$value\n";
}
untie %dbhash;