|
Perl-Referenzen
Ausführung von
externem Code mittels do()
Wird die Zahl der Subroutinen in einem Programm immer größer oder
verwendet man dieselben (oder ähnliche) Unterprogramme immer wieder in verschiedenen
Programmen, so sollte man den Programmcode auf mehrere Dateien verteilen. Es empfiehlt
sich, das Hauptprogramm zusammen mit ein paar wichtigen Subroutinen in einer Datei zu
speichern (die dann als Perl-Skript ausgeführt wird), und alle anderen Subroutinen (bzw.
Klassen bei objekt-orientierter Programmierung) - in logischen Gruppen zusammen gefaßt -
in eigenen Dateien abzulegen.
Um nun Programmcode aus einer zusätzlichen Datei in ein Hauptprogramm einzubinden,
gibt es in Perl verschiedene Möglichkeiten.
Die einfachste ist die Verwendung der Funktion "do()". Hiermit wird
Programmcode aus einer externen Datei so wie er dort abgelegt ist in das aktuelle Programm
(also an die Stelle, wo do steht) eingebaut und ausgeführt (so als würde man eval() auf den Dateiinhalt anwenden).
Datei prog.pl:
#!/usr/local/bin/perl -w
print "Erste Zeile des Hauptprogramms\n";
do "funkt.pl";
print "Ende des Hauptprogramms\n";
|
Datei funkt.pl:
print "Ausgabe aus 'funkt.pl'\n";
|
Erste Zeile des Hauptprogramms
Ausgabe aus 'funkt.pl'
Ende des Hauptprogramms
|
Wie man sieht, erwartet do() als Argument einen Dateinamen. Diese Datei wird
dann in allen Verzeichnissen gesucht, die im Array @INC aufgelistet sind. Befindet
sich die gesuchte Datei in einem Verzeichnis, das nicht standardmäßig zu @INC gehört, so kann der Pfad (vor dem Aufruf von do()) beispielsweise durch
push(@INC,$verzeichnispfad);
hinzugefügt werden.
Ein Nachteil von do() ist die Tatsache, das jedes mal, wenn diese Funktion
aufgerufen wird, die entsprechende Datei geöffnet, gelesen und geparst wird, weswegen
sich der Einsatz z.B. innerhalb einer oft durchlaufenen Schleife nicht gerade empfiehlt.
Code-Einbindung
mit Hilfe von require()
Die Funktion require() bindet im Prinzip genauso wie do() Programmcode aus einer externen Datei ein, allerdings mit dem Unterschied, daß das
Einlesen nur einmal geschieht und Perl beim nächsten Aufruf schon "weiß", daß
sich der entsprechende Code schon im Speicher befindet und nicht wieder neu geladen werden
muss.
Datei prog.pl:
#!/usr/local/bin/perl -w
print "Erste Zeile des Hauptprogramms\n";
require "funkt.pl";
print "Ende des Hauptprogramms\n";
|
Datei funkt.pl:
print "Ausgabe aus 'funkt.pl'\n";
|
Erste Zeile des Hauptprogramms
Ausgabe aus 'funkt.pl'
Ende des Hauptprogramms
|
Ebenso wie do() durchsucht auch require() alle Verzeichnispfade in @INC.
Ein wesentlicher Unterschied zu do() besteht aber darin, daß der Code in der
eingebundenen Datei bei der Ausführung eine "wahren" Wert (true)
zurückliefern muss. Im obigen Beispiel ist dies relativ offensichtlich, da der Aufruf "print
..." eine wahren Wert ("1") zurückgibt (auch wenn er meist nie
verwendet wird). Um sicherzugehen, daß externer Code wirklich zum Schluss true liefert, hat es sich eingebürgert, ans Ende der Datei eine kurze Zeile mit dem Inhalt
"1;" anzuhängen - sie bewirkt die Auswertung von "1", was true entspricht und ist der letzte Aufruf der Datei und somit der Rückgabewert an require().
Die Datei funkt.pl aus obigem Beispiel sollte also besser so aussehen:
print "Ausgabe aus 'funkt.pl'\n";
1;
|
Eine zweite Besonderheit von require(), die bei der Verwendung von sogenannten
Modulen ausgenutzt wird, ist die Tatsache, daß falls als Argument ein Name angegeben
wird, der nicht einen in Anführungsstrichen stehenden String darstellt, an diesen Namen
automatisch die Endung .pm hinzugefügt wird. Somit sind die Aufrufe im folgenden
Beispiel völlig äquivalent:
#!/usr/local/bin/perl -w
$dateiname = "extern.pm";
require $dateiname;
require 'extern.pm';
require extern; # Automatische Ergänzung von .pm
|
Während die Dateiendung .pl üblicherweise für Skripten/Programme genutzt
wird, verwendet man .pm für Dateien, die Perl-Module enthalten.
Verwendung von use()
Noch leistungsfähiger als require() ist die Funktion use().
Von der Funktion her entspricht ein use-Aufruf dem einen von require gefolgt
von import. Letztere ist keine von Perl vordefinierte Funktion sondern eine
Funktion, die in einem einzubindenden Modul definiert wird und üblicherweise dazu
verwendet wird, um Funktionsnamen zu importieren, damit sie dann genauso wie andere
Funktionen im Hauptprogramm aufgerufen werden können.
Ein zweiter Unterschied besteht darin, daß use() nicht (wie require())
an der entsprechenden Stelle zur Laufzeit des Hauptprogramms abgearbeitet wird, sondern
schon bei der Kompilierung des Programms.
Datei prog.pl:
#!/usr/local/bin/perl -w
print "Erste Zeile des Hauptprogramms\n";
use modul; # eigentlich "modul.pm"
print "Ende des Hauptprogramms\n";
|
Datei modul.pm:
print "Ausgabe aus 'modul.pm'\n";
1;
|
Ausgabe aus 'modul.pm'
Erste Zeile des Hauptprogramms
Ende des Hauptprogramms
|
An der Reihenfolge der Ausgabe erkennt man schon, daß der Code der Datei modul.pm schon abgearbeitet wird, bevor das eigentliche Hauptprogramm beginnt.
Eine wichtige Konsequenz davon ist, daß man nun nicht mehr durch eine Zeile wie
push(@INC,$verzeichnispfad);
vor dem use-Aufruf im Hautprogramm einen zusätzlichen Suchpfad angeben kann, da use() schon abgearbeitet wird, bevor überhaupt eine Zeile des Hauptprogramms zur
Ausführung kommt. Zur Lösung dieses Problems kann man den entsprechenden push-Befehl
in einen BEGIN { ... }-Block einbetten, so daß auch diese Funktion
zur Kompilierungszeit aufgerufen wird.
Datei prog.pl:
#!/usr/local/bin/perl -w
BEGIN {
$pfad = 'subdir';
push(@INC,$pfad);
}
print "Erste Zeile des Hauptprogramms\n";
use modul;
print "Ende des Hauptprogramms\n";
|
Datei modul.pm im Unterverzeichnis subdir :
print "Ausgabe aus 'modul.pm'\n";
1;
|
Ein Beispiel für ein zweidimensionales
Array ist eine sogenannte Matrix. Dabei handelt es sich zunächst
einfach um eine Anordnung von Zahlen (oder Variablen oder Termen oder...)
in einem Feld, wobei jeder Eintrag durch zwei Kennziffern (Indizes)
bestimmt ist.
Beispiel einer 2x3-Matrix (2 Zeilen, 3
Spalten):
| A= |
SIZE="+4">( |
|
SIZE="+4">) |
|
Um eine einzelne Variable
zu beschreiben, setzt man Zeile und Spalte als Index an
den Namen der Matrix, z.B.:
Will man nun ein Perl-Programm
schreiben, das mit Matrizen arbeiten soll, muß man sich überlegen,
wie man sie geeignet speichert. Da Arrays ein geordnetes eindimensionales
(ein Index) Schema darstellen, ließe
sich eine Matrix wohl aus der Kombination von Arrays repräsentieren.
Wie es nicht geht
Die einfachste Idee scheint
zu sein, die Zeilen jeweils in einzelnen Arrays zu speichern
und dann diese Zeilen-Arrays in ein Matrix-Array einzusetzen:
#!/usr/local/bin/perl -w
@zeile_1 = ( 'a', 'b', 'c' );
@zeile_2 = ( 'd', 'e', 'f' );
@matrix = ( @zeile_1, @zeile_2 );
# 6-elementiges Array !
|
Obiger Code erzeugt keineswegs
eine zweidimensionale Matrix in @matrix. In der
letzten Zeile werden nämlich zuerst die beiden Zeilen-Arrays @zeile_1 und @zeile_2 als
Listen dargestellt, die dann vor der Zuweisung zu einer
6-elementigen Liste vereinigt werden. Die letzte Zeile
des obigen Programms ist also äquivalent zu:
@matrix = (
'a', 'b', 'c', 'd', 'e', 'f' );
|
Die Ursache für dieses
Verhalten liegt darin begründet, daß Arrays in Perl
grundsätzlich nur skalare Größen enthalten, aber
keine Arrays oder Hashe (sie werden, wie oben beschrieben,
vorher umgewandelt).
Verwendung von Referenzen
Einen Ausweg aus dem Dilemma
bieten Referenzen, da sie skalare Variablen sind, aber
auf beliebige Datentypen (so auch Arrays) "zeigen" können.
#!/usr/local/bin/perl -w
@zeile_1 = ( 'a', 'b', 'c' );
@zeile_2 = ( 'd', 'e', 'f' );
@matrix = ( \@zeile_1, \@zeile_2 );
|
Nun enthält das Array @matrix zwei
(skalare) Elemente, die ihrerseits jeweils eine Referenz
auf ein Zeilen-Array sind.
Wie kann man nun auf die
einzelnen Matrixelemente zugreifen ? Die Elemente $matrix[0] und $matrix[1] enthalten
jeweils eine Referenz auf ein Array, so daß nach der Dereferenzierung
die Zeilen-Arrays zur Verfügung stehen.
An dieser Stelle sei noch
einmal darauf hingewiesen, daß in Perl Array-Indizes üblicherweise
bei 0 anfangen. Man sollte nicht die Variable $[ auf
1 setzen, um bei 1 mit der Zählung zu beginnen, sondern
besser die Elemente oder Zeilen-Arrays gezielt an die Positionen
1,2,... der jeweiligen Arrays schreiben. Der Einfachheit
halber wird in den Beispielen auf dieser Seite darauf verzichtet,
so daß zu beachten ist, daß von den Matrix-Indizes immer
jeweils 1 zu subtrahieren ist, um die Array-Indizes zu
erhalten.
Ein ausführliches Beispiel sieht
dann so aus:
#!/usr/local/bin/perl -w
@zeile_1 = ( 'a', 'b', 'c' );
@zeile_2 = ( 'd', 'e', 'f' );
@matrix = ( \@zeile_1, \@zeile_2 );
$ref_1 = $matrix[0];
@zeile_1 = @$ref_1;
$ref_2 = $matrix[1];
@zeile_2 = @$ref_2;
print "1) @zeile_1\n";
print "2) @zeile_2\n";
|
Der Zugriff läßt sich natürlich
auch kompakter programmieren:
@matrix = ( \@zeile_1, \@zeile_2 );
print "1) @{$matrix[0]}\n";
print "2) @{$matrix[1]}\n";
|
Wegen der Präzedenzregeln
müssen bei den Dereferenzierungen hier geschweifte
Klammern gesetzt werden (ansonsten würde Perl zuerst
versuchen, $matrix zu dereferenzieren und erst dann
dort das Element mit dem entsprechenden Index suchen).
Mit Hilfe dieses Mechanismus
lassen sich auch gezielt einzelne Matrixelemente auslesen
und mit Werten besetzen:
#!/usr/local/bin/perl -w
@zeile_1 = ( 'a', 'b', 'c' );
@zeile_2 = ( 'd', 'e', 'f' );
@matrix = ( \@zeile_1, \@zeile_2 );
print "Matrix(1,2) =
${$matrix[0]}[1] \n";
${$matrix[1]}[2] = 'x';
print "1) @{$matrix[0]}\n";
print "2) @{$matrix[1]}\n";
|
Matrix(1,2) = b
1) a b c
2) d e x
|
Eine alternative Schreibweise
für den Zugriff auf ein einzelnes Element bietet der
Pfeil-Operator "->"(nicht zu verwechseln
mit "=>" als Kommaersatz):
print "Matrix(1,2) =
$matrix[0]->[1] \n";
$matrix[1]->[2] = 'x';
|
Und auch dies läßt
sich noch verkürzen, da Perl zwischen zwei aufeinander
folgenden Klammern (eckig oder geschweift) automatisch
einen Pfeil-Operator setzt. Dadurch läßt sich eine
sehr intuitive und übersichtliche Schreibweise erreichen:
print "Matrix(1,2) =
$matrix[0][1] \n";
$matrix[1][2] = 'x';
|
Anonyme Arrays
Wie der Name schon vermuten
läßt, handelt es sich dabei um Arrays, die keinen
eigenen Variablennamen besitzen. Die einzige Möglichkeit,
auf den Inhalt zuzugreifen, besteht in einer Referenz auf
dieses Array. Erzeugen kann man ein solches Array, indem
man bei einer Liste eckige anstelle von runden Klammern
verwendet. Der Rückgabewert ist dann eine Referenz
auf diese Liste.
Beispiel:
#!/usr/local/bin/perl -w
@array = ( 10, 20, 30, 40 );
# normales Array
$ref_array =
[ 10, 20, 30, 40 ]
; # anonymes Array
|
Da ein solches anonymes
Array eine Referenz liefert, kann man daraus direkt mehrdimensionale
Felder erstellen. Die weiter oben als Beispiel verwendete
Matrix ließe sich dann auch so erzeugen:
#!/usr/local/bin/perl -w
@matrix = ( [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] );
|
Noch einmal zur Erinnerung:
würde man hier runde statt eckige Klammern verwenden,
erhielte man ein einfaches 6-elementiges Array in @matrix.
Auf die Matrixeinträge
kann hier genauso zugegriffen werden wie weiter oben bei
den benannten Arrays beschrieben.
Ein Beispiel, wie man die
gesamte Matrix ausgeben kann:
#!/usr/local/bin/perl -w
@matrix = ( [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] );
foreach $ref_zeile (@matrix) {
foreach $spalte (@$ref_zeile) { print "$spalte " }
print "\n";
}
|
Da eine solche zweidimensionale
Datenstruktur letztlich auf (eindimensionalen) Arrays beruht,
kann man sie mit Hilfe bekannter Funktionen wie push() oder pop() dynamisch
verändern. So läßt sich die oben definierte Matrix
beliebig bearbeiten:
#!/usr/local/bin/perl -w
@matrix = ( [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ] );
pop( @{$matrix[1]} );
# 'f' entfernen
unshift( @{$matrix[0]}, 'M' );
# 'M' einfügen
push(@matrix, [ sort( 'i', 'h', 'g' ) ] );
# 3.Zeile
foreach $ref_zeile (@matrix) {
foreach $spalte (@$ref_zeile) { print "$spalte " }
print "\n";
}
|
Wie man sieht, wird auch
der (Array-)Rückgabewert einer Funktion (hier: sort())
durch [...] in ein anonymes Array umgewandelt.
Eine Variable, die ein Array
in Perl darstellt, ist durch das Zeichen "@" gekennzeichnet.
Da skalare Variablen und Arrays unabhängig voneinander
verwaltet werden, darf es in einem Programm durchaus eine
Zahl $ALF und ein Array @ALF geben.
Arrays sind grundsätzlich
eindimensional (Vektoren) und enthalten als Elemente skalare
Größen. Wie bei Zeichenketten muss auch bei Arrays
keine Speicherplatzreservierung vorgenommen werden und
Arrays können im Laufe eines Programms praktisch beliebige
Größen annehmen. Versucht man, auf ein nicht definiertes
oder gesetztes Element zuzugreifen, so erhält man
eine "0" im Zahlenkontext bzw. einen Leerstring "" im
Zeichenkettenkontext zurück (intern besitzt die Variable
den Wert "undef").
Die Elemente eines Arrays
können im wesentlichen auf zwei Arten mit Werten besetzt
werden :
- @vector = (4,6,"ein String",25);
Hier bekommen die
ersten vier Elemente von @vector die entsprechenden
Werte.
- $vector[7] = 42;
Bei der Zuweisung über
einen Index ist hier das Dollar-Zeichen $ zu
beachten, da "vector[7]" eine skalare Variable
und kein Array darstellt ! Die Indizierung der Arrays
beginnt normalerweise bei 0 (Dies kann durch Änderung
der reservierten Variablen $[ beeinflußt werden
- z.B. $[=1 - , kann aber unter Perl 5 zu
Problemen führen, da dort diese Zuweisung nur
innerhalb eines Files gilt). In diesem Beispiel müssen übrigens
die Inhalte $vector[0] bis $vector[6] überhaupt
nicht besetzt werden.
Die Länge eines Arrays
kann bestimmt werden, indem man die Array-Variable in einem
skalaren Kontext verwendet; den Index des letzten Elements
erhält man durch Voranstellen von "$#" vor
den Arraynamen.
#!/usr/local/bin/perl -w
@vector = (4,6,"ein String",25);
$laenge = @vector;
# skalarer Kontext !
print "Laenge = $laenge\n";
print "Letzter Index = $#vector\n";
print "\$vector[1] = $vector[1]\n";
$vector[7] = 42;
$laenge = @vector;
print "Laenge = $laenge\n";
print "Letzter Index = $#vector\n";
|
Laenge = 4
Letzter Index = 3
$vector[1] = 6
Laenge = 8
Letzter Index = 7
|
Aus einem Array kann auch
ein Ausschnitt ("slice") genommen werden, indem
der entprechende Indexbereich angegeben wird.
#!/usr/local/bin/perl -w
@vector = (2,4,6,8,10,12);
@slice = @vector;
# (2,4,6,8,10,12)
@slice = @vector[2,3,4];
# (6,8,10)
@slice = @vector[2,4];
# (6,10)
@slice = @vector[3..5];
# (8,10,12)
|
Ein spezielles Array ist @ARGV.
Es enthält die Parameter/Optionen, die dem Skript
beim Aufruf mit übergeben werden. Beispiel:
#!/usr/local/bin/perl -w
foreach $i (@ARGV) { print $i."\n" }
|
ACHTUNG : Im Gegenteil zur
Programmiersprache C liefert $ARGV[0] den ersten
Parameter und nicht den Namen des Programms (Dieser Filename
befindet sich in Perl in der Variablen $0) !
Assoziative Arrays
Kennzeichen eines assoziativen
Arrays ("hash") ist die Paarung von jeweils zwei
Elementen in der Form "Schlüssel-Wert".
Gekennzeichnet wird ein assoziatives Array durch ein Prozentzeichen "%" vor
dem Variablennamen.
#!/usr/local/bin/perl -w
%alter = ("Sabine","27","Klaus","35","Ralf","22");
print "$alter{Sabine}\n";
print "$alter{Klaus}\n";
print "$alter{Ralf}\n";
foreach $key (keys(%alter))
# foreach
{
print "$key\n"
# (hier ";" nicht unbedingt noetig)
}
|
27
35
22
Klaus
Sabine
Ralf
|
Hier wird auf die Werte
der Schlüssel in %alter durch $alter{...} zugegriffen
(man beachte auch hier das Dollar-Zeichen). Eine Liste
aller Schlüssel in einem assoziatien Array erhält
man durch die Funktion keys(); analog kann man eine
Liste aller Werte durch values() bekommen. Die Reihenfolge
der Elemente ist dabei willkürlich und muß keineswegs
mit der in der Definition übereinstimmen (obige Ausgabe
ergab sich unter MacPerl).
Man kann die Elemente eines
assoziativen Arrays mit Hilfe der Funktion each() auch
paarweise jeweils in ein zweielementiges Array lesen.
#!/usr/local/bin/perl -w
%h = ("Auto" => 1,"Haus" => 2,"Baum" => 3);
while(@a = each(%h)) {
print "$a[0] ($a[1])\n";
}
|
Haus (2)
Auto (1)
Baum (3)
|
Die Reihenfolge ist auch
hier (scheinbar) willkürlich - sie hängt von
der internen Speicherung der Daten ab.
In diesem Beispiel wurde
anstelle von Kommata ein Pfeil-Symbol ( "=>")
verwendet. Dieses Symbol ist einem Komma vollkommen gleichwertig
und wird bei assoziativen Arrays gerne der Übersichtlichkeit
halber verwendet, um die Schlüssel-Wert-Paarungen
zu verdeutlichen.
Unter UNIX kann auf die
Umgebungsvariablen (environment) über das assoziative
Array %ENV zugegriffen werden.
Beispiel:
#!/usr/local/bin/perl -w
print $ENV{'LOGNAME'}."\n";
print $ENV{'DISPLAY'}."\n";
|
Zu einer "richtigen" Programmiersprache
gehören natürlich Variablen, die mit Werten besetzt
werden können. Zunächst einmal sollen nur "skalare" Variablen
betrachtet werden. Dies sind Zahlen und Zeichenketten (Strings).
Im Unterschied zu vielen anderen Sprachen sehen die Variablen
für Zahlen und Zeichen in Perl gleich aus: sie beginnen
alle mit einem $ gefolgt von einer Kombination aus
Buchstaben und Ziffern.
#!/usr/local/bin/perl -w
$ausgabe = "Just another Perl hacker\n";
$i = 123;
$x = 1e-26;
print "$ausgabe\n";
print "$i\n";
print "$x\n";
|
Just another Perl hacker
123
1e-26
|
In diesem Beispiel enthält
die Variable $ausgabe den Wert Just another Perl
hacker\n, die Variable $i den Wert 123 und $x den
Wert 1e-26.
Im Unterschied zu den meisten
anderen Sprachen müssen Variablen in Perl nicht zu
Beginn eines Programms definiert werden. Auch für
Zeichenketten muß kein Speicherplatz reserviert werden,
ihre Länge ist in Perl nur durch die Größe des
Hauptspeichers begrenzt.
Zahlen sind in Perl grundsätzlich
Gleitkommazahlen, d.h, es gibt keine Ganzzahlen. Die Genauigkeit
entspricht dem Zahlentyp double in C (meist 8 Bytes).
Ob eine Variable als Zahl
oder Zeichenkette interpretiert wird, hängt von der
Umgebung - dem Kontext - ab, in dem sie auftritt.
#!/usr/local/bin/perl -w
$a = 1;
$b = 4;
$c = $a + $b;
$d = $a . $b;
print "$c\n";
print "$d\n";
|
Im obigen Beispiel ist "+" der
normale Operator zur Addition zweier Zahlen und "." der
Verkettungsoperator, um zwei Strings zu einem zu verbinden.
Lokale Variablen
In einem Unterprogramm kann
beliebig auf die (globalen) Variablen des Hauptprogramms
zugegriffen werden. Um Variablen lokal zu definieren gibt
es die Operatoren local und my. Sie unterscheiden
sich in bezug auf Unterprogramme darin, daß Variablen,
die in my deklariert werden, nur dort im Unterprogramm
definiert sind (genauer: innerhalb des Blockes, in dem
sie deklariert werden). Auf "local"-Variablen
dagegen kann auch in weiteren Unterprogrammen zugegriffen
werden, deren Aufruf innerhalb des Unterprogramms erfolgt,
in dem die Variablen deklariert werden.
Beispiel:
#!/usr/local/bin/perl -w
$gl = 1;
$loc = 2;
$my = 3;
print "main: \$gl = $gl \$loc = $loc \$my = $my\n";
sub1();
print "main: \$gl = $gl \$loc = $loc \$my = $my\n";
sub sub1 {
local $loc = 7;
my $my = 8;
print "sub1: \$gl = $gl \$loc = $loc \$my = $my\n";
sub2();
}
sub sub2 {
print "sub2: \$gl = $gl \$loc = $loc \$my = $my\n";
}
|
main: $gl = 1 $loc = 2 $my = 3
sub1: $gl = 1 $loc = 7 $my = 8
sub2: $gl = 1 $loc = 7 $my = 3
main: $gl = 1 $loc = 2 $my = 3
|
Wie man sieht, ist $gl überall
unverändert verfügbar, während $loc in sub1durch
eine neue Variable gleichen Namens ersetzt wird. Deren
Wirkung erstreckt sich aber bis in das zweite Unterprogramm.
Dagegen ist die Zuweisung $my = 8 nur in sub1 von
Bedeutung. An der letzten Ausgabezeile erkennt man, daß die
Werte der globalen Variablen von den lokalen Variablen
gleichen Namens nicht beeinflusst werden.
Lexikalische
Variablen mittels my()
Jede Variable, die "einfach
so" (wie diejenigen im Beispiel des vorherigen Abschnittes)
verwendet wird, wird in die Symboltabelle des jeweils aktuellen
Packages aufgenommen.
Deklariert man dagegen eine
Variable mit dem Operator my, so wird die entsprechende
Variable in einer anderen Tabelle abgelegt, auf die kein
expliziter Zugriff möglich ist.
#!/usr/local/bin/perl
$var_1 = 42;
my $var_2 = "Perl";
foreach $v (keys %::) { ### Symboltabelle von "main"
if($v =~ /^var/) { print "$v\n" }
}
|
Hier erscheint in der Programmausgabe
nur "$var_1", nicht aber "$var_2".
Neben der Tatsache, daß my-Variablen
in einer eigenen Tabelle verwaltet werden, ist von besonderer
Bedeutung, daß sie nur einen recht beschränkten Gültigkeitsbereich
besitzen. Während nicht besonders deklarierte Variablen
(wie $var_1 im obigen Beispiel) im gesamten Package
benutzt werden können (und über den voll qualifizierten
Namen wie etwa $main::var_1 auch in anderen Packages),
so ist eine durch my erzeugte Variable nur in dem
aktuellen Block (definiert durch geschweifte Klammern "{...}"),
der aktuellen Datei oder innerhalb eine Arguments von eval() zugänglich.
Es kann in einem Package
durchaus zwei Variablen gleichen Namens geben: eine in
der Symboltabelle und eine, die durch einen Aufruf von my entstanden
ist. In einem solchen Falle wird bei einfacher Verwendung
des Bezeichners auf die my-Variable zugegriffen.
#!/usr/local/bin/perl -w
$a = "main";
{
my $a;
$a = "Block";
print "$a\n"; ### "Block"
print "$main::a\n"; ### "main"
}
print "$a\n";
### "main"
|
Im Block in der Mitte des
Programms existiert neben "$a" der Symboltabelle
von main (Zugriff über voll qualifizierten
Namen "$main::a" möglich) auch eine my-Variable
gleichen Namens. Letztere verschwindet aber wieder, sobald
der umschließende Block verlassen wird.
Es ist übrigens durchaus
möglich, my-Deklarationen zu "schachteln":
#!/usr/local/bin/perl -w
my $a = "main";
{
my $a;
$a = "Block";
print "$a\n"; ### "Block"
}
print "$a\n";
### "main"
|
Man bezeichnet solche Variablen
als lexikalisch, weil deren Gültigkeitsbereich
schon alleine durch Untersuchung des Programmcodes feststellbar
ist.
Benötigt man in einem
Perl-Programm eine lokale Variable, so sollte man im allgemeinen my verwenden.
Lediglich in speziellen Situationen ist es angebracht,
stattdessen local (siehe nächsten Abschnitt)
zu benutzen.
Dynamische
Variablen mittels local()
Auch der
Operator local schränkt den Gültigkeitsbereich
einer Variablen ein. Allerdings unterscheidet sich der
Mechanismus grundlegend von dem des Operators my.
Wird eine
Variable durch local deklariert, so wird der aktuelle
Wert dieser Variablen (sofern vorhanden) gesichert. Anschließend
können dieser Variablen neue Werte zugewisen werden.
Wird der Block, in dem die local-Deklaration erfolgte,
verlassen, so wird der ursprüngliche (gesicherte)
Wert wiederhergestellt.
#!/usr/local/bin/perl -w
$a = 123;
print "Main: $a\n";
{
local $a;
$a = 456;
print "Block: $a\n";
}
print "Main: $a\n";
|
Main: 123
Block: 456
Main: 123
|
Bei der
Deklaration mit local wird keine neue Variable
auf irgendeinem Stack erzeugt (wie bei my), sondern
es wird nur der Inhalt neu zur Verfügung gestellt.
Die entsprechende Variable ist also nach wie vor global
zugänglich.
Daß die
Variable nach wie vor eine globale Variable ist, erkennt
man auch im folgenden Beispiel:
#!/usr/local/bin/perl -w
$x = 'x (main)';
print "Main: \$x = $x\n";
{
local $x = 'x (local)';
print "Block: \$x = $x\n";
print "Symboltabelle: \$::x = $::x\n";
unterpr();
}
print "Main: \$x = $x\n";
sub unterpr {
print "unterpr(): \$x = $x\n";
}
|
Main: $x = x (main)
Block: $x = x (local)
Symboltabelle: $::x = x (local)
unterpr(): $x = x (local)
Main: $x = x (main)
|
Sowohl
in der (globalen) Symboltabelle als auch in der Subroutine unterpr(),
die sich, betrachtet man den Quell-Code des Programms,
außerhalb des Blockes mit der local-Deklaration
befindet, wird für $x der Wert "x
(local)" ausgegeben. Der ursprüngliche
Wert wird erst wiederhergestellt, wenn in der Folge des
Programmablaufs der Block verlassen wird, in dem die local-Deklaration
stattfand.
Da die
Gültigkeit von local-Variablen somit durch
den Programmablauf bestimmt wird, spricht man auch von Laufzeit- oder dynamischen Variablen.
Unterschiede
zwischen my() und local()
Die folgende
Tabelle zeigt noch einmal schematisch den Unterschied
zwischen my und local. Rot markiert sind
diejenigen Werte, die ein " print $v;" an
der entsprechenden Stelle im Code ausgeben würde.
| |
von main |
my-Variablen |
local-Stack |
|
| $v = 42; |
v = 42 |
|
|
Globales $v |
{
local $v = 100; |
v = 100 |
|
v = 42 |
Inhalt von $v wird
ersetzt |
{
my $v = 7; |
v = 100 |
v = 7 |
v = 42 |
Lexikalische Variable $v |
| } |
v = 100 |
|
v = 42 |
Ende des my-Blocks |
| } |
v = 42 |
|
|
Ende des local-Blocks |
Auf die
Variable in der Symboltabelle kann in diesem Beispiel
immer mittels $main::v zugegriffen werden. Existiert
zusätzlich eine my-Variable, so bezieht sich $v immer
auf diese (nicht auf das globale $v). Ein Zugriff
auf den local-Stack ist hingegen nicht möglich.
Eine Situation,
in der lokale Variablen nicht mittels my erzeugt
werden können, sind die speziellen in Perl vordefinierten
Variablen, wie etwa $"(Zeichen, das die Elemente
eines Arrays voneinander trennt, wenn es innerhalb von
doppelten Anführungszeichen interpoliert wird).
Man kann so in einem Programmblock eine Neudefinition
einer globalen Variable vornehmen, ohne den ursprünglichen
Wert explizit sichern und am Ende wieder zurücksetzen
zu müssen.
#!/usr/local/bin/perl -w
$" = ',';
@a = (10,20,30);
print "@a\n";
{
local $" = ' - ';
print "@a\n";
}
print "@a\n";
|
10,20,30
10 - 20 - 30
10,20,30
|
Spezielle Variablen
In den vorherigen Abschnitten wurden schon
einige spezielle Perl-Variablen im Zusammenhang mit der Mustersuche erwähnt;
hier eine Übersicht:
- $& gibt das gefundene Muster zurück
- $1,$2,$3,... enthält das Muster der 1.,2.,3.,...
runden Klammer
- $+ enthält das Muster der letzten runden
Klammer
- $` enthält die Zeichenkette, die vor dem
gefundenen Muster steht
- $' enthält die Zeichenkette, die hinter
dem gefundenen Muster steht
Beispiel:
#!/usr/local/bin/perl -w
$a = "Dies ist ein Test ...";
if($a =~ /is([a-z]) (.*) Test/) {
print $&."\n";
print $1."\n";
print $2."\n";
print $+."\n";
print $`."\n";
print $'."\n";
}
|
ist ein Test
t
ein
ein
Dies
...
|
reservierte Variablen
Es gibt in Perl einige reservierte Variablen,
die Informationen über aktuelle Einstellungen geben und die auch
dazu verwendet werden können, einige dieser Einstellungen zu verändern,
indem die Variablen entsprechend gesetzt werden.
Anmerkung: Einige der Variablen liefern
auf Nicht-UNIX-Betriebssystemen nicht unbedingt sinnvolle Werte (wenn überhaupt),
falls die jeweils zugrundeliegende Funktion (z.B. Verwendeung von Benutzer-IDs)
nicht zur Verfügung steht.
Die Variable $_
Wenn beispielsweise bei einem Funktionsaufruf
der Rückgabewert nicht explizit einer Variablen zugewiesen wird,
so wird er oft doch gespeichert, und zwar in der Variablen "$_".
Auch können eine Reihe von Funktionen (die eigentlich ein Argument
erwarten) ohne Argument aufgerufen werden - es wird dann stillschweigend
der Inhalt von $_ übergeben. $_ ist also so etwas wie
eine Variable, die temporär Daten aufnimmt, und es daher erlaubt,
Funktionsaufrufe miteinander zu verketten, ohne jedes mal explizit Zuweisungen
an Variablen vornehmen zu müssen, die sonst nirgendwo im Programm
gebraucht werden.
Beispiel:
#!/usr/local/bin/perl -w
$string = 'Hallo';
chop($string);
print $string;
print "\n";
$_ = 'Hallo';
chop($_);
print $_;
print "\n";
$_ = 'Hallo';
chop;
print;
print "\n";
|
Während im ersten Teil eine Variable
namens $string verwendet wird, um den Text zu speichern und die
anschließenden Funktionsaufrufe durchzuführen, zeigt das zweite Beispiel,
daß man als Variable genau sogut $_ verwenden kann. Der dritte
Teil demonstriert, wie bei Aufruf der Funktion chop ohne
Argument standardmäßig der Inhalt von $_ übergeben wird
und das Ergebnis wiederum in $_ landet. Schließlich wird der Inhalt
von $_ mit der Funktion print (ebenso ohne Argument) ausgegeben.
Auch wenn im obigen Beispiel $_ wie
eine normale Variable verwendet wird, gibt es ein doch ein paar Unterschiede;
so ist $_ auch über package -Deklarationen hinweg
global, und sie lässt sich auch nicht mit my in
einer Subroutine lokalisieren.
Ein weiteres Beispiel:
Da hier bei foreach keine
Laufvariable angegeben ist, wird $_ angenommen. $_ erhält
also nacheinander die Werte "a", "b" und "c".
Im Inneren der Schleife wird die Funktion tr auf $_ angewandt
(ausführlich sähe dies so aus: $_ =~ tr/a-z/A-Z/;),
die hier die Kleinbuchstaben von a bis z durch die entsprechenden Großbuchstaben
ersetzt.
Allgemeine
Informationen zu Variablen
PID | UID
| GID
Fehlermeldungen
Weitere
spezielle Variablen
Die Übergabe von Parametern
erfolgt durch das spezielle Array "@_".
Somit kann innerhalb des Unterprogramms auf die (im Prinzip
beliebig vielen) Parameter über $_[0],$_[1],$_[2],...
zugegriffen werden.
Beispiel:
#!/usr/local/bin/perl -w
&S(1,2);
&S("aaa","bbb","ccc","ddd");
sub S {
local($i);
for($i = 0;$i < @_;$i++) { print "$_[$i]\n" }
}
|
Zur Erinnerung: @_ steht
im obigen Beispiel im skalaren Kontext und gibt daher die
Zahl der Elemente in dem Parameter-Array an.
Um einen bestimmten Wert
an das aufrufende Hauptprogramm zu liefern, kann die Funktion return() (Klammern
optional) verwendet werden. Fehlt eine solche Angabe, so
ist der Rückgabewert automatisch das Ergebnis der
zuletzt ausgeführten Operation im Unterprogramm.
#!/usr/local/bin/perl -w
$a = &S(7,19);
print $a."\n";
$a = &T;
print $a."\n";
sub S { $_[0] + $_[1] }
sub T { return 100; }
|
|
Schleifen und Bedingungen |
|
|
Bedingte Verzweigung
#!/usr/local/bin/perl -w
for($i = 1;$i <= 5;$i ++) {
if ($i < 3) { print "($i) kleiner als 3\n" }
elsif ($i == 4) { print "($i) gleich 4\n" }
elsif ($i > 4) { print "($i) größer als 4\n" }
else { print "($i) keine der anderen Bedingungen erfüllt\n" }
unless($i == 2) { print "[$i] ungleich 2\n" }
}
|
(1) kleiner als 3
[1] ungleich 2
(2) kleiner als 3
(3) keine der anderen Bedingungen erfuellt
[3] ungleich 2
(4) gleich 4
[4] ungleich 2
(5) groesser als 4
[5] ungleich 2
|
Das Argument von if ist
eine Bedingung, die entweder wahr ("true") oder
falsch ("false") ist. Im Falle von "wahr" wird
der Block nach if ausgeführt. Ist die if-Bedingung
falsch, so wird (falls vorhanden) das Argument des ersten elsif ausgewertet.
Liefert auch dieses nicht den Wert true, kommt das nächste elsif an
die Reihe; so lange bis entweder eine Bedingung wahr ist,
keine Bedingungen mehr vorhanden sind oder ein abschließendes else erreicht
wird, dessen Block ausgeführt wird, falls kein anderer
Block infrage kommt.
Im Gegensatz zu anderen
Programmiersprachen wie z.B. C muß der Block nach einem if, elsif oder else immer
in geschweiften Klammern stehen; dadurch werden eventuelle
Mehrdeutigkeiten vermieden.
Das Gegenstück von if ist unless,
dessen Block nur ausgeführt wird, wenn die Bedingung
im Argument den Wert false liefert.
Eine Alternative zu einer if- else-Konstruktion
ist die Verwendung des Operators "?:":
$a == 1 ? print "a gleich 1" : print "a ungleich 1";
while und until
#!/usr/local/bin/perl -w
$i = 0;
while($i < 10) {
print "$i\n";
$i += 2;
}
until($i == 5) {
print "$i\n";
$i --;
}
|
Bei der while-Schleife
wird zuerst das Argument überprüft. Falls dies true liefert,
wird der Schleifenblock ausgeführt. Dies wiederholt
sich so lange, bis das while-Argument false ist.
Die Negation der while-Schleife
ist die Konstruktion mit Hilfe von until. Hier wird
der Schleifenkörper so lange wiederholt bis das Argument
von until den Wert true liefert. Obiges Programm
liefert demzufolge die Ausgabe
for und foreach
Folgendes Programm schreibt
die Zahlen von 1 bis 10 auf den Bildschirm:
#!/usr/local/bin/perl -w
for($i = 1;$i <= 10;$i++) { print "$i\n"; }
|
Zu allererst wird die Anweisung
im 1.Argument von for ausgeführt. Anschließend
wird das 2.Argument überprüft. Liefert diese
Abfrage eine wahre Aussage (true), so wird der Schleifenblock
ausgeführt. Nach dem Block wird das 3.Argument von for ausgewertet
und dann wieder das Argument Nummer 2 überprüft.
Dies wiederholt sich so lange, bis die Bedingung (Argument
2) nicht mehr erfüllt ist (Wert false). Dann
fährt das Programm in der Zeile nach dem Schleifenblock
fort.
Die for-Schleife
ist eigentlich nur eine vereinfachte Schreibweise; obiges
Beispielprogramm läßt sich auch wie folgt schreiben:
#!/usr/local/bin/perl -w
$i = 1;
while($i <= 10) {
print "$i\n";
$i++;
}
|
Anstatt der drei durch Semikolons
getrennten Argumente, kann for auch eine Liste übergeben
werden, die dann sukzessive abgearbeitet wird. Aus Gründen
der Übersichtlichkeit sollte in so einem Falle aber an
Stelle von for das äquivalente foreach stehen.
Die einzelnen Zeilen des folgenden Skripts leisten alle
das gleiche: Sie geben die Zahlen von 1 bis 10 aus.
#!/usr/local/bin/perl -w
for((1,2,3,4,5,6,7,8,9,10)) { print $_."\n" }
foreach((1,2,3,4,5,6,7,8,9,10)) { print $_."\n" }
foreach(1..10) { print $_."\n" }
foreach $nr (1..10) { print $nr."\n" }
|
In der letzten Zeilen sieht
man, wie das gerade von foreach bearbeitete Listenelement
einer Variablen zugewiesen werden kann. Wird keine solche
Variable angegeben, so steht der aktuelle Listenwert in
der speziellen Variablen $_.
Globbing
In einer UNIX-Shell gibt
es die Möglichkeit, eine Liste von Files zu erhalten,
indem man ein Muster vorgibt, das Platzhalter wie * oder ? enthält.
So liefert
ls -1 *.html
eine einspaltige Liste aller
Files, die auf .html enden.
Einen analogen Mechanismus
gibt es in Perl durch die Funktion glob() sowie
den sog. Rhombus-Operator <>. Obiges Shell-Beispiel
lässt sich dann wie folgt implementieren:
Oder auch:
#!/usr/local/bin/perl -w
foreach $filename (<*.html>) {
print $filename."\n"
}
|
Man kann auch die Fileliste direkt an ein
Array übergeben:
#!/usr/local/bin/perl -w
$pfad = 'perl';
@fileliste = <$pfad/*.html>;
foreach $filename (@fileliste) { print $filename."\n" }
$muster = '*.html';
@fileliste = <${muster}>; # Spezialfall ...
foreach $filename (@fileliste) { print $filename."\n" }
|
Im obigen Beispiel muss
im zweiten Teil <${muster}> anstelle von <$muster> stehen,
da hier eine Variable alleine im Rhombus-Operator steht.
Wer es etwas genauer wissen
will: in einem Ausdruck wie <$muster> wird $muster als "indirektes
Filehandle" betrachtet. Damit kann man beispielsweise
Filehandles als Parameter an Unterprogramme übergeben.
Beispiel:
#!/usr/local/bin/perl -w
open(FILE,'test.dat');
print_file(\*FILE);
close(FILE);
sub print_file {
my $handle = $_[0];
while(<$handle>) { print }
}
|
Verzeichnisse
Ähnlich wie man Dateien
zum Lesen öffnen kann, lassen sich auch Verzeichnisse
behandeln, um auf die Dateinamen des Ordnerinhalts zugreifen
zu können.
Beispiel:
#!/usr/local/bin/perl -w
opendir(DIR,"perl");
while($datei = readdir(DIR)) { print $datei."\n" }
closedir(DIR);
|
Mit opendir() wird
dabei das Verzeichnis geöffnet. Das erste Argument
ist hierbei das sog. "Directoryhandle", dessen
Name (aus Gründen der Konvention) aus Großbuchstaben
bestehen sollte. Die Funktion readdir() liefert
dann die einzelnen Einträge des Ordners. closedir() schließlich
beendet den Zugriff auf das Verzeichnis.
Das aktuelle Verzeichnis
kann durch `pwd` bestimmt werden. Zu beachten sind
hier die sog. backquotes (``) ! Sie bewirken,
daß die eingeschlossene Zeichenkette als Kommando an das
Betriebssytem weitergegeben wird. Das Ergebnis des Kommandos
wird dann zurückgeliefert.
Beispiel:
#!/usr/local/bin/perl -w
$akt_verz = `pwd`;
print "aktuelles Verzeichnis : $akt_verz\n";
|
Ein Verzeichniswechsel ist
durch die Funktion chdir() möglich. Dies ist
allerdings abhängig vom Betriebssystem, unter dem
Perl gerade läuft, wobei insbesondere auf das Zeichen
zu achten ist, das Datei-/Verzeichnisnamen im Pfad voneinander
trennt.
Als Beispiel seien hier
UNIX und MacOS gegenübergestellt:
| UNIX | MacOS
----------------------+-------------------+---------------------
Pfad-Trennzeichen | / | :
| |
Wechseln in höheres | chdir('..'); | chdir('::');
Verzeichnis | |
| |
Öffnen des aktuellen | opendir(ABC,'.'); | opendir(ABC,':');
Verzeichnisses | |
Dateifunktionen
Zum Arbeiten mit Dateien gibt es folgende Funktionen;
abhängig vom Betriebssystem stehen nicht immer alle zur Verfügung (z.B. gibt es
keine Hard Links auf der Macintosh-Plattform):
Eine einfache Möglichkeit, Protokolle
oder Tabellen übersichtlich auszugeben, bieten sogenannte
Formate. Dort können beispielsweise Spalten einer
Tabelle definiert werden; jeweils mit Breite und Positionierung
des Eintrags (rechts-, linksbündig oder zentriert).
Außerdem kann ein Seitenkopf definiert werden, der bei
Ausgaben, die sich über mehrere Seiten erstrecken,
auf jeder einzelnen Seite vor den eigentlichen Daten
ausgedruckt wird.
Um Daten formatiert auszugeben, muss
der Befehl write (optional mit einem Filehandle)
benutzt werden. Es können für jedes Filehandle
unabhängig voneinander Formate definiert werden.
Definition eines Formats
Das Schema einer Formatdefinition sieht
wie folgt aus:
format <Name> =
<Musterzeile>
<Variablenzeile>
.
Im einfachsten Falle ist der Name eines
Formats gleich dem Namen des Filehandles, für das
das Format verwendet werden soll (Standardwert: STDOUT).
Will man einer Formatdefinition einen anderen Namen geben,
so kann die entsprechende Zuordnung von Formatname und
aktuellem Filehandle durch Setzen der Variablen $~ geschehen.
Um bei mehrseitigen Dokumenten jeweils
automatisch einen Seitenkopf ausgeben zu lassen, kann
ein spezielles Format hierfür definiert werden.
Der Name wird gebildet durch das Anhängen von "_TOP" an
das Filehandle (Standardwert: STDOUT_TOP). Alternativ
dazu kann eine beliebiger Name durch Setzen von $^ verwendet
werden. Ansonsten erfolgt die Definition vollkommen analog
zu der eines normalen Formats.
Die Musterzeile enthält die Definitionen
der einzelnen Felder, in die dann später die Werte
der Variablen der darauffolgenden Zeile eingetragen werden.
Es dürfen mehrere Muster- und Variablenzeilen angegeben
werden; allerdings ist darauf zu achten, dass sie immer
paarweise auftreten (jede Variablenliste "füllt" die
darbüberstehende Musterzeile).
Außerdem können noch überall
Kommentarzeilen eingefügt werden, die mit einem
'#' beginnen.
Die Definitionen von Formaten dürfen
an beliebiger Stelle im Programmcode stehen (wie Unterprogramme).
Musterzeile
Jede dieser Zeilen bestimmt Felder in
der Ausgabe, in die dann Variablenwerte (festgelegt in
der jeweils darauffolgenden Zeile) eingesetzt werden
sollen.
Ein normales Feld besteht aus einem '@'
gefolgt von null oder mehr Positionierungszeichen eines
Typs:
| '<' (linksbündig) |
'|' (zentriert) |
'>' (rechtsbündig) |
Beispiel:
#!/usr/local/bin/perl -w
$a = 12;
write;
format STDOUT =
# eine Spalte, vierstellig, zentriert
@|||
$a
.
|
Eine mehrzeilige Ausgabe von Zeichenketten
wird durch Felder bewerkstelligt, die mit einem '^'
beginnen. Dabei wird dann dort, wo das Feld in der Formatdefinition
zum ersten Mal erscheint, ein möglichst großer Teil
des Ausgabestrings dargestellt. Beim zweiten Auftreten
wird ggf. dann ein Teil des Restes dargestellt, usw.
(Achtung: in der Zeichenkette wird dabei sukzessive der
jeweils dargestellte Teil entfernt, d.h., der Wert der
Stringvariablen ändert sich u.U. bei jedem write).
Beispiel:
#!/usr/local/bin/perl -w
$text = "Dies ist ein Beispiel dafuer, wie einem Format mehrzeilige ";
$text .= "Texteintraege dargestellt werden koennen.";
write;
format STDOUT =
# bis zu drei Zeilen Text
|
Dies ist ein Beispiel dafuer,
wie einem Format mehrzeilige
Texteintraege dargestellt ...
|
Oft weiß man vorher nicht, wie lang der
Text wird. Um unnötige Leerzeilen zu vermeiden,
setzt man einfach in die entsprechende Musterzeile eine
Tilde ('~'). Will man einen längeren Text
auf jeden Fall komplett ausgeben, so kann man dies durch
zwei aufeinanderfolgende Tilden ('~~') in einer
Musterzeile erreichen. In diesem Falle wird die Ausgabe
dieser Zeile so oft wiederholt bis die Zeichenkette in
der dazugehörenden Stringvariable vollständig
dargestellt ist. Schließlich kann ein Text in seiner
natürlichen Zeilenaufteilung in ganzer Länge
ausgegeben werden, indem der Stringvariablen in der Musterzeile
das Feld '@*' zugeordnet wird.
Eine besondere Art der Positionierung
bietet das '#'. Nach einem '@' bewirkt
es eine rechtsbündige Darstellung, wobei bei der
Ausgabe einer Zahl ein optionaler Dezimalpunkt berücksichtigt
wird. Nach einem '^' wird ein so markiertes Feld
nur dann dargestellt, wenn die dazugehörende Variable
definiert ist.
Beispiel:
#!/usr/local/bin/perl -w
$a = 117.127;
write;
format STDOUT =
Betrag: @###.## € (^###)
$a, $b
.
|
Variablenzeile
Eine Zeile dieser Art legt fest, welche
Variablenwerte in die jeweils vorangegangene Musterzeile
eingetragen werden sollen.
Dies kann einfach durch eine durch Kommata
getrennte Liste sein; aber es ist auch möglich,
Arrays (die mehrere Felder der Musterzeile abdecken)
oder gar ganze Ausdrücke |