You are here: Perldoc Web>PerlDokumentListe>Perldata (2006-01-18)
perldata Dokumentation zu Perl 5.8.0 | Download als POD | Wie kann ich hier etwas ändern?

NAME

perldata - Perldatentypen

BESCHREIBUNG

Variablennamen

Perl besitzt drei eingebaute Datentypen: Skalare, Arrays von Skalaren und assoziative Arrays von Skalaren, auch "Hashes" genannt. Normale Arrays sind geordnete Listen von Skalaren, deren Elemente über numerische Indizes, beginnend mit 0, ansprechbar sind. Negative Subskripte zählen rückwärts vom Ende der Liste her. Hashes sind ungeordnete Mengen von skalaren Werten, die durch ihnen zugeordnete Zeichenkettenschlüssel indiziert sind.

Werte werden in der Regel durch einen Namen oder eine benannte Referenz angesprochen. Das erste Zeichen des Namens sagt Dir, auf welche Art von Datenstruktur er verweist. Der Rest des Namens sagt Dir, auf welchen spezifischen Wert er verweist. Normalerweise ist dieser Name ein einziger Bezeichner , also eine Zeichenkette, die mit einem Buchstaben oder Unterstrich beginnt und die Buchstaben, Unterstriche und Ziffern enthalten kann. In manchen Fällen kann der Name aber auch aus einer Kette von Bezeichnern, getrennt durch :: (oder das etwas archaische ' ), bestehen; alle bis auf den letzten Bezeichner werden als Paketnamen interpretiert um den Namensraum zu lokalisieren in dem der letzte Bezeichner nachgeschlagen werden soll (siehe perlmod, Packages für detailliertere Informationen). Es ist möglich einen einfachen Bezeichner durch einen Ausdruck zu ersetzen, der zur Laufzeit eine Referenz auf den Wert erzeugt. Im Detail wird dies weiter unten und in perlref beschrieben.

Perl besitzt auch eigene eingebaute Variablen, deren Namen nicht diesen Regeln folgen. Sie haben seltsame Namen um nicht zufällig mit denen Deiner eigenen Variablen zu kollidieren. Zeichenketten, die auf eingeklammerte Teile eines regulären Ausdrucks passen, werden unter Namen gespeichert, welche nur Ziffern nach dem $ enthalten (siehe perlop und perlre). Ferner haben verschiedene Spezialvariablen, die Einblicke ins Innenleben von Perl gewähren, Namen, die Interpunktions- und Steuerzeichen enthalten. Sie sind in perlvar dokumentiert.

Die Namen skalarer Werte beginnen stets mit '$', selbst wenn auf ein Skalar bezug genommen wird, welches Teil eines Arrays oder Hashes ist. Das Symbol '$' verhält sich semantisch so wie der Artikel "das", da es anzeigt, dass ein einzelner Wert erwartet wird.

    $tage               # der einfache skalare Wert "tage"
    $tage[28]           # das 29. Element des Arrays @tage
    $tage{'Feb'}        # der mit 'Feb' indizierte Wert aus dem
                        # Hash %tage
    $#tage              # der letzte Index des Arrays @tage

Ganze Arrays (und Scheiben von Arrays und Hashes) werden durch Voranstellen des Symbols '@' notiert, welches ähnliche Auswirkungen wie der Artikel "die" hat, da es anzeigt, dass mehrere Werte erwartet werden.

    @tage               # ($tage[0], $tage[1],... $tage[n])
    @tage[3,4,5]        # äquivalent zu ($tage[3],$tage[4],$tage[5])
    @tage{'a','c'}      # äquivalent zu ($tage{'a'},$tage{'c'})

Ganze Hashes werden durch Voranstellen des Symbols '%' notiert:

    %tage               # (Schlüssel1, Wert1, Schlüssel2, Wert2 ...)

Subroutinen werden ferner mit einem vorangestellten '&' bezeichnet, das allerdings optional ist, sofern dadurch keine Mehrdeutigkeiten entstehen, so wie auch das Wort "do" im Englischen oft redundant ist. Einträge in Symboltabellen können mit einem vorangestellten '*' bezeichnet werden, allerdings brauchst Du dich darum im Moment noch nicht zu kümmern (so Du es überhaupt jemals musst :-).

Jeder Variablentyp hat seinen eigenen Namensraum und auch einige Nicht-Variablenbezeichner haben ihren. Das bedeutet, dass Du, ohne Konflikte befürchten zu müssen, denselben Namen für eine skalare Variable, ein Array oder einen Hash verwenden kannst -- oder auch, was das betrifft, für ein Dateihandle, ein Verzeichnishandle, einen Subroutinennamen, einen Formatnamen oder eine Sprungmarke. Es bedeutet, dass $foo und @foo zwei verschiedene Variablen sind. Es bedeutet auch, dass $foo[1] ein Teil von @foo aber nicht von $foo ist. Das mag ein wenig seltsam erscheinen, aber das ist in Ordnung so, denn es ist tatsächlich seltsam.

Da Variablenreferenzen stets mit '$', '@' oder '%' beginnen, sind die "reservierten" Wörter nicht wirklich reserviert, was Variablennamen betrifft. Sie sind allerdings reserviert wenn es um Sprungmarken und Dateihandles geht, die nicht durch ein besonderes erstes Zeichen gekennzeichnet werden. Du kannst zum Beispiel kein Dateihandle mit dem Namen "log" benutzen. Tip: Du könntest open(LOG,'logfile') statt open(log,'logfile') schreiben. Dateihandles in Großbuchstaben zu schreiben verbessert auch die Lesbarkeit Deines Codes und hilft Dir, Konflikte mit zukünftigen reservierten Wörtern zu vermeiden. Die Groß- und Kleinschreibung ist signifikant -- "FOO", "Foo" und "foo" sind alle drei unterschiedliche Namen. Namen, die mit einem Buchstaben oder Unterstrich beginnen, dürfen auch Ziffern und Unterstriche enthalten.

Es ist möglich solch einen alphanumerischen Namen durch einen Ausdruck zu ersetzen, der eine Referenz auf den passenden Datentyp zurückgibt. Siehe auch perlref für eine Beschreibung dieser Möglichkeit.

Namen, die mit einer Ziffer beginnen, dürfen auch ansonsten nur weitere Ziffern enthalten. Namen, die nicht mit einem Buchstaben, Unterstrich, einer Ziffer oder einem Kontrollzeichen beginnen, dürfen nur aus genau einem Zeichen bestehen, zum Beispiel $% oder $$ . (Die meisten dieser ein Zeichen langen Namen haben eine vordefinierte Bedeutung für Perl. Zum Beispiel enthält $$ die Identifikationsnummer des aktuellen Prozesses.)

Kontext

Die Interpretation von Operationen und Werten hängt in Perl bisweilen von den Anforderungen des Kontexts um die Operation oder den Wert herum ab. Es gibt im wesentlichen zwei Arten von Kontext: Liste und Skalar. Gewisse Operationen geben Listen zurück, wenn der Kontext eine Liste verlangt und andernfalls Skalare. Wenn dies auf eine Operation zutrifft, so wird es in ihrer Dokumentation erwähnt. In anderen Worten: Perl überläd bestimmte Operationen auf Grundlage der Entscheidung ob der erwartete Rückgabewert Singular oder Plural ist. Manche Wörter des Deutschen funktionieren so ähnlich, zum Beispiel "Eichhörnchen" und "Feuer".

Umgekehrt betrachtet stellt eine Operation für jedes ihrer Argumente entweder Skalar- oder einen Listekontext bereit. Schreibst du zum Beispiel

    int( <STDIN> )

so stellt die int Anweisung Skalarkontext für den <>-Operator bereit, welcher daraufhin eine einzelne Zeile von STDIN liest und sie an die int-Anweisung zurückgibt, die nun den Ganzzahlwert dieser Zeile ermittelt und zurückgibt. Schreibst Du aber andererseits

    sort( <STDIN> )

so stellt die sort Anweisung Listenkontext für <> bereit, welcher daraufhin jede verfügbare Zeile bis zum Dateiende einliest und die Liste der Zeilen an die sort-Routine zurückgibt, die nun die Zeilen sortiert und sie als Liste zurückgibt an was immer der Kontext von sort war.

Zuweisungen sind ein Sonderfall, da sie ihr linkes Argument begutachten um den Kontext für ihr rechtes Argument zu bestimmen. Zuweisungen zu einem Skalar werten ihre rechte Seite im Skalarkontext aus während Zuweisungen zu einem Array oder Hash ihre rechte Seite im Listenkontext auswerten. Zuweisungen zu einer Liste (oder eine Scheibe eines Arrays, die auch nur eine Liste ist) werten ihre rechte Seite ebenfalls im Listenkontext aus.

Wenn Du das use warnings -Pragma oder Perls -w - Kommandozeilenoption benutzt, stößt du unter Umständen auf Warnungen über den "Useless use of a (constant|variable) in void context", den sinnlosen Gebrauch von Konstanten oder Variablen im leeren Kontext. Leerer Kontext bedeutet schlichtweg, dass der Rückgabewert verworfen wurde, wie zum Beispiel in den Anweisungen "fred"; oder getpwuid(0); . Diese Situation zählt aber trotzdem als Skalarkontext für Funktionen, die sich darum kümmern ob sie im Skalar- oder Listenkontext aufgerufen wurden.

In benutzerdefinierten Subroutinen kann man sich entscheiden, ob man sich darum kümmern will, ob sie in leerem, Skalar- oder Listenkontext aufgerufen werden. Bei den meisten Subroutinen muss man sich darum aber keine Gedanken machen, denn sowohl Skalare als auch Listen werden automatisch in Listen interpoliert. Siehe auch perlfunc, wantarray für eine Beschreibung, wie Du dynamisch den Aufrufkontext Deiner Funktion bestimmen kannst.

Skalare Werte

Alle Daten in Perl sind Skalare, Arrays von Skalaren oder Hashes von Skalaren. Ein Skalar kann einen einzelnen Wert in einer von drei Varianten enthalten: Eine Zahl, eine Zeichenkette oder eine Referenz. Im allgemeinen geschieht die Umwandlung von einer Form in die andere ohne Zutun des Programmierers automatisch. Obschon ein Skalar nicht unmittelbar mehrere Werte aufnehmen kann, ist es möglich, eine Referenz auf ein Array oder einen Hash, die wiederum mehrere Werte enthalten, darin zu speichern.

Skalare sind nicht zwingend eine Sache oder eine andere. Es gibt keine Stelle, an der man festlegen könnte, dass eine Skalarvariable vom Typ "Zeichenkette", "Zahl", "Referenz" oder irgendetwas anderes ist. Wegen der automatischen Umwandlung von Skalaren müssen sich Operationen, die Skalare zurückgeben, nicht darum kümmern, ob ihr Aufrufer eine Zeichenkette, eine Zahl oder eine Referenz erwartet. (Im Endeffekt können sie sich auch gar nicht darum kümmern.) Perl ist eine kontextuell polymorphe Sprache, deren Skalare Zeichenketten, Zahlen oder Referenzen (was Objekte einschließt) sein können. Obwohl Zeichenketten und Zahlen für fast alle Zwecke mehr oder weniger als dasselbe angesehen werden, sind Referenzen stark typisierte, nicht im Zieltyp veränderliche Zeiger auf Datenstrukturen mit eingebautem Referenzzähler und automatisch aufgerufenem Destruktor.

Ein skalarer Wert wird im Booleschen Sinne als "wahr" angesehen, wenn er weder die Nullzeichenkette noch die Zahl 0 (oder ihr Zeichenkettenäquivalent "0") ist. Der Boolesche Kontext ist lediglich eine spezielle Art von Skalarkontext in dem niemals eine Umwandlung in Zeichenketten oder Zahlen durchgeführt wird.

In der Tat gibt es zwei Varianten der Nullzeichenkette (manchmal auch als "leere" Zeichenkette bezeichnet), eine definierte und eine undefinierte. Die definierte Version ist schlicht eine Zeichenkette der Länge Null, wie "" . Die undefinierte Version ist der Wert, der anzeigt, dass kein richtiger Wert für etwas vorhanden ist, zum Beispiel wenn ein Fehler aufgetreten ist, am Ende einer Datei oder wenn Du auf eine nicht initialisierte Variable oder ein nicht initialisiertes Element in einem Array oder Hash zugegriffen hast. Obwohl in frühen Versionen von Perl ein undefiniertes Skalar zu einem definierten werden konnte sobald es das erste Mal an einer Stelle, wo ein definierter Wert erwartet wurde, benutzt wurde, geschieht dies nun nicht mehr außer in seltenen Fällen der automatischen Belebung, wie sie in perlref erläutert werden. Du kannst den defined()-Operator nutzen, um festzustellen, ob ein skalarer Wert definiert ist (auf Arrays oder Hashes angewendet hat dieser Ausdruck keine Bedeutung) und den undef()-Operator um einen undefinierten Wert zu erzeugen.

Um herauszufinden, ob eine gegebene Zeichenkette eine gültige, von Null verschiedene Zahl ist, ist es manchmal ausreichend, sie sowohl mit der numerischen 0 als auch mit der lexikalischen "0" zu vergleichen (obwohl das mit -w unnötige Warnungen produziert). Das liegt daran, dass Zeichenketten, die keine Zahlen sind, als 0 zählen, genau wie in awk :

    if ($str == 0 && $str ne "0")  {
        warn "Das sieht nicht nach einer Zahl aus";
    }

Diese Methode mag die beste sein, denn andernfalls wirst Du IEEE Notationen wie NaN oder Infinity nicht korrekt behandeln. Zu anderen Zeiten willst Du aber vielleicht lieber feststellen, ob die Daten einer Zeichenkette numerisch verwendet werden können indem Du die POSIX::strtod()-Funktion aufrufst oder Deine Zeichenkette mittels eines regulären Ausdruckes (wie sie in perlre dokumentiert sind) inspizierst.

    warn "Enthält Nicht-Ziffern" if     /\D/;
    warn "Keine natürliche Zahl" unless /^\d+$/;          # lehnt -3 ab
    warn "Keine ganze Zahl"      unless /^-?\d+$/;        # lehnt +3 ab
    warn "Keine ganze Zahl"      unless /^[+-]?\d+$/;
    warn "Keine Dezimalzahl"     unless /^-?\d+\.?\d*$/;  # lehnt .2 ab
    warn "Keine Dezimalzahl"     unless /^-?(?:\d+(?:\.\d*)?|\.\d+)$/;
    warn "Keine C-Fließkommazahl"
        unless /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;

Die Länge eines Arrays ist ein skalarer Wert. Die Länge des Arrays @tage kannst Du herausfinden, indem du $#tage auswertest, so wie in csh . Dies ist jedoch nicht die Länge des Arrays; es ist das Subskript des letzten Elementes, was ein anderer Wert ist, denn in der Regel gibt es ein 0. Element. Eine Zuweisung an $#tage ändert tatsächlich die Länge des Arrays. Verkürzt man ein Array auf diesem Wege, so werden überschüssige Werte zerstört. Verlängert man ein Array, das zuvor verkürzt wurde, so werden dadurch die Werte in jenen Elementen nicht wiederhergestellt. (In Perl 4 war dem noch so, aber wir mussten dieses Verhalten ändern um sicherzustellen, dass Destruktoren dann aufgerufen würden, wann man es erwartet.)

Du kannst auch einen winzigen Effizienzgewinn erzielen, indem Du ein Array, das groß werden wird, im Vorfeld vergrößerst. Du kannst ein Array aber auch vergrößern, indem Du einem Element hinter dem Ende des Arrays einen Wert zuweist. Du kannst ein Array zum leeren Array zurückstutzen, indem Du ihm die Nulliste () zuweist. Folgende Ausdrücke sind äquivalent:

    @irgendwas = ();
    $#irgendwas = -1;

Wenn Du ein Array im Skalarkontext auswertest, wird die Länge des Arrays zurückgegeben. (Beachte, dass das nicht für Listen der Fall ist, die den letzten ihrer Werte zurückgeben, so wie der Kommaoperator in C, und auch nicht für eingebaute Funktionen, die zurückgeben, wonach auch immer ihnen gerade ist.) Der folgende Ausdruck ist stets wahr:

    scalar(@irgendwas) == $#irgendwas - $[ + 1;

Version 5 von Perl veränderte die Semantik von $[ : Dateien, die den Wert von $[ nicht setzen, müssen sich keine Sorgen machen, ob eine andere Datei diesen Wert verändert haben könnte. (Mit anderen Worten, vom Gebrauch von $[ wird abgeraten.) Generell kannst Du also annehmen, dass

    scalar(@irgendwas) == $#irgendwas + 1;

Einige Programmierer entscheiden sich dafür eine explizite Konversion zu benutzen, um keine Zweifel aufkommen zu lassen:

    $elementanzahl = scalar(@irgendwas);

Wertest du einen Hash in Skalarem Kontext aus, so wird falsch zurückgegeben, wenn der Hash leer ist. Gibt es irgendwelche Schlüssel/Wert-Paare, so ist der Rückgabewert wahr; genauer ist der zurückgegebene Wert eine Zeichenkette bestehend aus der Anzahl verwendeter Behälter und der Anzahl allozierter Behälter, getrennt durch einen Schrägstrich. Dies ist fast nur nützlich um herauszufinden, ob Perls interner Hashalgorithmus mit Deinem Datensatz schlechte Leistung zeigt. Zum Beispiel, wenn Du 10000 Werte in einen Hash steckst, die Auswertung von %HASH im Skalarkontext aber ergibt "1/16" , was bedeutet, dass nur einer von sechzehn Behältern in Gebrauch ist und vermutlich alle Deine 10000 Objekte enthält. Das sollte normalerweise nicht passieren.

Du kannst für einen Hash Speicherplatz vorreservieren, indem Du der Funktion keys() einen Wert zuweist. Dabei werden die zu allozierenden Behälter auf die nächste Zweierpotenz aufgerundet:

    keys(%benutzer) = 1000;             # alloziere 1024 Behälter

Konstruktoren für skalare Werte

Numerische Literale werden in einem der folgenden Fließkomma- oder Ganzzahlformate angegeben:

    12345
    12345.67
    .23E-10             # eine sehr kleine Zahl
    3.14_15_92          # eine sehr wichtige Zahl
    4_294_967_296       # die Unterstriche dienen der Lesbarkeit
    0xff                # hexadezimal
    0xdead_beef         # noch mehr hexadezimal
    0377                # oktal
    0b011011            # binär

Du darfst Unterstriche in numerischen Literalen zwischen den Ziffern verwenden, um die Lesbarkeit zu verbessern. Du könntest, zum Beispiel, Binärziffern in Dreiergruppen anordnen (zum Beispiel für ein Zugriffsrechteargument im Unixstil wie 0b110_100_100), in Vierergruppen (um Nibbles herauszustellen wie in 0b1010_0110) oder in anderen Gruppen.

Zeichenkettenliterale sind in der Regel entweder durch einfache oder doppelte Anführungszeichen begrenzt. Sie verhalten sich großenteils wie Anführungszeichen in den standardmäßigen Unixshells: In in doppelte Anführungszeichen gesetzten Zeichenketten werden Backslashes und Variablen interpoliert; in in einfache Anführungszeichen gesetzten nicht (mit Ausnahme von \' und \\ ). Die üblichen Backslashregeln im C-Stile werden zum bilden von Zeichen wie Zeilenumbruch, Tabulator, usw. angewendet. Ferner existieren exotischere Formen. Siehe perlop, Quote and Quote-like Operators für eine Liste.

Hexadezimale, oktale oder binäre Repräsentationen in Zeichenkettenliteralen (zum Beispiel '0xff') werden nicht automatisch in ihre Dezimaldarstellung konvertiert. Die Funktionen hex() und oct() erledigen diese Umwandlungen für Dich. Siehe perlfunc, hex and perlfunc, oct für weitere Details.

Du kannst Zeilenumbrüche auch direkt in Deine Zeichenketten einbetten, das heißt, sie können auf einer anderen Zeile enden, als sie beginnen. Das ist nett, aber wenn Du Deine abschließenden Anführungszeichen vergisst, wird der Fehler nicht bemerkt bevor Perl eine weitere Zeile mit dem Anführungszeichen darin findet, was viel später im Skript sein kann. Variablensubstitution in Zeichenketten ist auf Skalarvariablen, Arrays und Scheiben von Arrays oder Hashes beschränkt. (Mit anderen Worten, Namen, die mit $ oder @ beginnen, optional gefolgt von einem Subskriptausdruck in eckigen oder geschweiften Klammern.) Das folgende Quellcodesegment druckt "Der Preis ist $100." aus

    $Preis = '$100';                  # nicht interpoliert
    print "Der Preis ist $Preis.\n";  # interpoliert

Wie auch in manchen Shells kannst Du die Variablennamen in geschweiften Klammern einschließen, um Mehrdeutigkeiten durch folgende alphanumerische Zeichen (und Unterstriche) zu vermeiden. Du musst dies auch bei der Interpolation einer Variable tun, um den Variablennamen von zwei folgenden Doppelpunkten oder einem Apostroph zu trennen, da sie sonst als Paketangabe behandelt würden:

    $who = "Larry";
    print PASSWD "${who}::0:0:Superuser:/:/bin/perl\n";
    print "We use ${who}speak when ${who}'s here.\n";

Ohne die geschweiften Klammern hätte Perl nach den Variablen $whospeak, $who::0 und $who's gesucht. Die beiden letzteren wären die $0 und $s variablen im (vermutlich) nicht existenten Paket who .

In der Tat ist ein Bezeichner zwischen solchen geschweiften Klammern gezwungernermaßen eine Zeichenkette, wie auch jeder einfache Bezeichner im Subskript eines Hashes. Keiner von beiden muss in Anführungszeichen gesetzt werden. Unser früheres Beispiel, $tage{'Feb'} kann auch als $tage{Feb} geschrieben werden und die Anführungszeichen werden automatisch als gegeben angenommen. Steht allerdings irgendetwas komplizierteres im Subskript, so wird es als Ausdruck interpretiert.

[Anmerkung des Übersetzers: v-Zeichenketten sorgen für Verwirrung und sind selten nützlich. Von Ihrer Verwendung wird abgeraten und nach Perl 5.8 sind sie nicht mehr verfügbar.]

Ein Literal der Form v1.20.300.4000 wird als Zeichenkette zusammengesetzt aus den Zeichen mit den angegebenen Ordinalen eingelesen. Diese Form, bekannt als v-Zeichenketten, bietet einen alternativen, besser lesbaren Weg um Zeichenketten zusammenzusetzen, anstelle die etwas schlechter lesbare interpolierende Form "\x{1}\x{14}\x{12c}\x{fa0}" zu verwenden. Dieser Weg ist nützlich um Unicode-Strings zu repräsentieren und um "Versionsnummern" mit Hilfe der Zeichenkettenvergleichsoperatoren cmp , gt , lt , etc. zu vergleichen. Wenn zwei oder mehr Punkte in dem Literal vorkommen kann das führende v weggelassen werden.

    print v9786;              # druckt einen UTF-8 codierten SMILEY,
                              # "\x{263a}"
    print v102.111.111;       # druckt "foo"
    print 102.111.111;        # dito

Derartige Literale werden von require und use akzeptiert um eine Versionsüberprüfung durchzuführen. Die Spezialvariable $^V enthält die Version des laufenden Perlinterpreters ebenfalls in dieser Form. Siehe L<perlvar/$^V>. Beachte, dass die Verwendung von v-Zeichenketten für IPv4 Adressen nicht portabel ist es sei denn Du benutzt zusätzlich die Funktionen inet_aton()/inet_ntoa() aus dem Socket-Paket.

Die speziellen Literale __FILE__ , __LINE__ und __PACKAGE__ repräsentieren den aktuellen Dateinamen, die Zeilennummer und den Paketnamen an der Stelle in Deinem Programm, wo sie auftreten. Sie können nur als separate Ausdrücke benutzt werden; sie werden nicht in Zeichenketten interpoliert. Falls es kein aktuelles Paket gibt (aufgrund einer leeren package; -Direktive) ist __PACKAGE__ der undefinierte Wert.

Die beiden Steuerzeichen ^D und ^Z sowie die Ausdrücke __END__ und __DATA__ können benutzt werden um das logische Ende des Skript vor dem eigentlichen Ende der Datei anzuzeigen. Jeglicher folgender Text wird ignoriert.

Text hinter __DATA__ kann allerdings über das Dateihandle PACKNAME::DATA eingelesen werden, wobei PACKNAME das Paket ist, welches aktuell war, als der Ausdruck __DATA__ angetroffen wurde. Das Dateihandle bleibt offen und zeigt auf den Dateiinhalt hinter __DATA__ . Das Programm ist verantwortlich dafür, es mittles close DATA zu schließen, wenn es fertig damit ist, daraus zu lesen. Um die Kompatibilität mit alten Skripten sicherzustellen verhält sich __END__ im Skript der obersten Ebene (aber nicht in Dateien, die mittels require oder do geladen werden) so wie __DATA__ und ermöglicht den Zugriff auf den verbleibenden Dateiinhalt über main::DATA .

Siehe SelfLoader für eine weitere Beschreibung von __DATA__ und ein Beispiel, wie es benutzt werden kann. Beachte, dass Du in einem BEGIN- Block nicht aus dem Dateihandle DATA lesen kannst: Der BEGIN_Block wird ausgeführt, sobald er vom Interpreter gesehen wird (während der Kompilation), doch zu diesem Zeitpunkt wurde der entsprechende __DATA__ (oder __END__ ) noch nicht vom Interpreter angetroffen.

Ein Wort, dem keine andere Interpretation in der Grammatik zugeordnet ist, wird wie eine in Anführungszeichen gesetzte Zeichenkette behandelt. Diese Wörter sind als "Barewords" bekannt. Wie auch bei Dateihandles und Sprungmarken riskiert ein Bareword, das ausschließlich aus Kleinbuchstaben besteht einen Konflikt mit zukünftigen reservierten Wörtern und wenn Du das use warnings -Pragma oder die -w -Kommandozeilenoption verwendest wird Perl Dich bei jedem solchen Wort warnen. Manche Leute wollen Barewords vielleicht komplett verbieten. Wenn Du

    use strict 'subs';

schreibst führt jedes Bareword, das NICHT als Subroutinenaufruf interpretiert würde stattdessen zu einem Fehler zum Zeitpunkt der Kompilation. Diese Einschränkung hält bis zum Ende des umschließenden Blockes an. In einem inneren Block kann dies durch no strict 'subs' aufgehoben werden.

Arrays und Scheiben werden in in doppelte Anführungszeichen gesetzten Zeichenketten interpoliert indem ihre Elemente verkettet werden mit dem Trennzeichen, das in der Variablen $" ( $LIST_SEPARATOR in English) spezifiziert ist, standardmäßig ein Leerzeichen. Die folgenden Ausdrücke sind äquivalent:

    $temp = join($", @ARGV);
    system "echo $temp";

    system "echo @ARGV";

Innerhalb von Suchmustern (die ebenfalls ähnlich wie in doppelten Änführungszeichen stehende Zeichenketten interpoliert werden) gibt es eine einheitliche Zweideutigkeit: Sollte /$foo[bar]/ als /${foo}[bar]/ interpretiert werden (wobei [bar] eine Zeichenklasse für den regulären Ausdruck ist) oder als /${foo[bar]}/ (wobei [bar] das Subskript des Arrays @foo ist)? Wenn @foo nicht anderweitig existiert, dann handelt es sich natürlich um eine Zeichenklasse. Wenn @foo existiert rät Perl geschickt, worum es sich bei [bar] handelt und liegt meistens richtig. Ist die geratene Variante verkehrt oder bist Du einfach paranoid, so kannst Du die korrekte Interpretation durch Verwendung geschweifter Klammern so wie oben erzwingen.

Falls Du nach der Information wie man Hier-Dokumente benutzt suchst, welche sich gewöhnlich hier befand, so lies stattdessen perlop, Quote and Quote-like Operators, wohin sie verschoben wurde.

Konstruktoren für Listenwerte

Listenwerte werden als individuelle Werte getrennt durch Kommata aufgeschrieben (und in Klammern eingeschlossen wo das auf Grund der Operatorenrangfolge notwendig ist):

    (LISTE)

In einem Kontext, der keinen Listenwert erfordert, ist der Wert von etwas, das eine literale Liste zu sein scheint, einfach der des letzten Elementes, so wie beim C Kommaoperator. Zum Beispiel weist

    @foo = ('cc', '-E', $bar);

die gesamte Liste dem Array @foo zu aber

    $foo = ('cc', '-E', $bar);

weist den Wert der Variablen $bar der Skalarvariable $foo zu. Beachte, dass der Wert eines echten Arrays im Skalarkontext die Länge des Arrays ist; der folgende Code weist $foo den Wert 3 zu:

    @foo = ('cc', '-E', $bar);
    $foo = @foo;                # $foo wird auf 3 gesetzt

Du darfst vor der schließenden Klammer eines Listenliterals ein optionales Komma setzen, so dass Du

    @foo = (
        1,
        2,
        3,
    );

schreiben kannst.

Um ein Hier-Dokument zu benutzen um ein Array zu füllen, ein Element pro Zeile, könntest Du einen Ansatz wie diesen verwenden:

    @sossen = <<Ende =~ m/(\S.*\S)/g;
        Normale Tomaten
        Würzige Tomaten
        Grünes Chili
        Pesto
        Weißwein
    Ende

In LISTEn werden Sublisten automatisch interpoliert. Wenn also eine LISTE ausgewertet wird, wird jedes ihrer Elemente im Listenkontext evaluiert und der resultierende Listenwert in die LISTE interpoliert genau so als ob jedes einzelne Element ein Bestandteil der LISTE wäre. Arrays und Hashes verlieren daher in einer LISTE ihre Identität -- die Liste

    (@foo,@bar,&IrgendEineSub,%glarch)

enthält alle Elemente von @foo, gefolgt von allen Elementen in @bar, allen Elementen, die die Subroutine namens IrgendEineSub aufgerufen im Listenkontext zurückgibt, und allen Schlüssel/Wert Paaren von %glarch. Zur Herstellung einer Listenreferenz, die NICHT interpoliert, siehe perlref.

Die Nulliste wird durch () repräsentiert. Sie in einer Liste zu interpolieren hat keinerlei Effekt. ((),(),()) ist daher äquivalent zu (). In ähnlicher Weise hat das Interpolieren eines Arrays ohne Elemente die gleiche Wirkung als ob kein Array an dieser Stelle interpoliert worden wäre.

Diese Eigenschaft der Interpolation verbindet sich mit den Tatsachen, dass öffnende und schließende Klammern optional sind (außer wo sie für die Rangfolge entscheidend sind) und dass Listen mit einem optionalen Komma enden dürfen zu der Folge, dass mehrfache Kommata innerhalb von Listen gültige Syntax sind. Die Liste 1,,3 ist eine Verkettung zweier Listen, 1, und 3 , deren erste mit dem optionalen Komma endet. 1,,3 ist (1,),(3) ist 1,3 . (Und ähnlich 1,,,3 ist (1,),(,),(3) ist 1,3 und so weiter.) Allerdings legen wir Dir nicht nahe, diese Verschleierungstaktik zu verwenden.

Ein Listenwert kann auch wie ein gewöhnliches Array mit einem Subskript versehen werden. Du musst die Liste in diesem Fall zur Vermeidung von Mehrdeutigkeiten in Klammern setzen. Zum Beispiel:

    # stat gibt einen Listenwert zurück.
    $zeit = (stat($datei))[8];

    # HIER STECKT EIN SYNTAXFEHLER DRIN.
    $zeit = stat($datei)[8];  # OOPS, KLAMMERN VERGESSEN

    # Find a hex digit.
    $hexziffer = ('a','b','c','d','e','f')[$ziffer-10];

    # Ein "umgekehrter Kommaoperator".
    return (pop(@foo),pop(@foo))[0];

Zuweisungen zu Listen sind nur gestattet, wenn jedes Element der Liste selbst gültiges Ziel für eine Zuweisung ist:

    ($a, $b, $c) = (1, 2, 3);

    ($tab{'rot'}, $tab{'blau'}, $tab{'gruen'}) = (0x00f, 0x0f0, 0xf00);

Eine Ausnahme dazu ist, dass Du zu undef in einer Liste zuweisen darfst. Das ist nützlich um einige Rückgabewerte einer Funktion zu verwerfen:

    ($dev, $ino, undef, undef, $uid, $gid) = stat($datei);

Listenzuweisungen geben im Skalarkontext die Anzahl der Elemente zurück, die von dem Ausdruck auf der rechten Seite der Zuweisung produziert wurden:

    $x = (($foo,$bar) = (3,2,1));       # setzt $x auf 3, nicht 2
    $x = (($foo,$bar) = f());           # setzt $x auf f()'s Zahl an
                                        # Rückgabewerten

Das ist nützlich wenn Du eine Listenzuweisung in booleschem Kontext verwenden willst, denn die meisten Listenfunktionen geben eine Nulliste zurück, wenn sie fertig sind, welche bei der Zuweisung eine 0 erzeugt, die als FALSCH interpretiert wird.

Es bildet auch die Grundlage einer nützlichen Schreibweise um eine Funktion oder Operation im Listenkontext auszuführen und anschließend die Anzahl der Rückgabewerte zu zählen, indem man zu einer leeren Liste zuweist und die Zuweisung dann im Skalarkontext verwendet. Zum Beispiel weist dieser Code:

    $zahl = () = $string =~ /\d+/g;

$zahl die Anzahl an Zifferngruppen zu, die in $string gefunden werden. Das passiert weil die Mustersuche im Listenkontext steht (denn sie wird der leeren Liste zugewiesen) und folglich eine Liste aller passenden Teile der Zeichenkette zurückgibt. Die Listenzuweisung im Skalarkontext übersetzt dies in die Anzahl von Elementen (hier die Anzahl von Treffern für das Suchmuster) und weist sie $zahl zu. Beachte, dass die einfache Verwendung von

    $count = $string =~ /\d+/g;

nicht funktioniert hätte, da eine Mustersuche im Skalarkontext nur wahr oder falsch anstelle einer Trefferanzahl zurückgeben würde.

Das letzte Element einer Listenzuweisung darf ein Array oder Hash sein:

    ($a, $b, @rest) = split;
    my($a, $b, %rest) = @_;

Eigentlich kannst du ein Array oder einen Hash überall in der Liste platzieren, aber das erste solche Element nimmt alle Werte auf und alles was dahinter steht wird undefiniert. Das kann in einer my() oder local() Anweisung von Nutzen sein.

Ein Hash kann mittels einer literalen Listen, die Paare von Ausdrücken enthält, welche jeweils als Schlüssel und Wert interpretiert werden sollen, initialisiert werden:

    # gleiches Resultat wie die tab-Zuweisung weiter oben
    %tab = ('rot',0x00f,'blau',0x0f0,'gruen',0xf00);

Während literale Listen und benannte Arrays oftmals austauschbar sind, ist das nicht für Hashes der Fall. Nur weil Du eine Liste wie ein normales Array mit einem Subskript versehen kannst heißt das nicht etwa, dass Du eine Liste mit einem Hashsubskript versehen könntest. Ebenso werden Hashes, die als Teile in anderen Listen enthalten sind (inklusive Parameterlisten und Rückgabelisten von Funktionen) stets in Schlüssel/Wert-Paare expandiert. Daher ist es manchmal gut, Referenzen zu verwenden.

Oftmals wird die Lesbarkeit verbesser, indem man den Operator => zwischen Schlüssel/Wert-Paare setzt. Der => -Operator ist im wesentlichen nur ein optisch herausstechenderes Synonym eines Kommas, aber er sorgt auch dafür, dass der Operand zu seiner linken Seite als Zeichenkette interpretiert wird -- falls es sich um ein Bareword handelt, dass ein zulässiger Bezeichner wäre. Das macht ihn besonders attraktiv für die Initialisierung von Hashes:

    %tab = (
                 rot   => 0x00f,
                 blau  => 0x0f0,
                 gruen => 0xf00,
   );

oder zum Initialisieren von Hashreferenzen, die als strukturierter Datensatz dienen sollen:

    $rec = {
                hexe   => 'Mable the Merciless',
                katze  => 'Fluffy the Ferocious',
                datum  => '10/31/1776',
    };

oder um eine "Aufruf durch benannte Parameter"-Konvention für komplizierte Funktionen zu realisieren:

   $feld = $abfrage->radio_gruppe(
               name          => 'guppenname',
               werte         => ['eene','meene','miste'],
               standard      => 'meene',
               zeilenumbruch => 'wahr',
               beschriftung  => \%beschriftung
   );

Beachte, dass ein Hash nicht diese Anordnung von Elementen behält, nur weil er in dieser Reihenfolge initialisiert wurde. Siehe perlfunc, sort für Beispiele, wie man eine Ausgabesortierung erreichen kann.

Scheiben

Ein üblicher Zugriffsweg auf ein Array oder einen Hash ist jeweils ein Element einzeln anzusprechen. Du kannst auch Listen mit einem Subskript versehen um ein einzelnes Element aus ihnen auszulesen.

    $werbinich = $ENV{"USER"};             # ein Element aus dem Hash
    $eltern    = $ISA[0];                  # ein Element aus dem Arras
    $verz      = (getpwnam("daemon"))[7];  # dito, aber mit einer Liste

Eine Scheibe greift auf mehrere Elemente einer Liste, eines Arrays oder eines Hashes simultan zu indem eine Liste von Subskripten verwenden wird. Das ist handlicher als das Aufschreiben der individuellen Elemente als Liste separater skalarer Werte.

    ($er, $sie)   = @leute[0,-1];              # Arrayscheibe
    @sie         = @leute[0 .. 3];            # Arrayscheibe
    ($wer, $home) = @ENV{"USER", "HOME"};      # Hashscheibe
    ($uid, $verz) = (getpwnam("daemon"))[2,7]; # Listenscheibe

Da Du Zuweisungen zu einer Liste von Variablen ausführen kannst, kannst du auch einer Array- oder Hashscheibe neue Werte zuweisen.

    @tage[3..5]    = qw/Mit Don Fre/;
    @farben{'rot','blau','gruen'} 
                   = (0xff0000, 0x0000ff, 0x00ff00);
    @leute[0, -1] = @leute[-1, 0];

Die vorangehenden Zuweisungen sind exakt äquivalent zu

    ($tage[3], $tage[4], $tage[5]) = qw/Mit Don Fre/;
    ($farben{'rot'}, $colors{'blau'}, $colors{'gruen'})
                   = (0xff0000, 0x0000ff, 0x00ff00);
    ($leute[0], $leute[-1]) = ($leute[-1], $leute[0]);

Da Veränderungen in einer Scheibe sich auf das ursprüngliche Array oder den ursprünglichen Hash, der in Scheiben geschnitten wurde, übertragen, verändert eine foreach -Konstruktion einige -- oder sogar alle -- Werte des Arrays oder Hashes.

    foreach (@array[ 4 .. 10 ]) { s/peter/paul/ } 

    foreach (@hash{keys %hash}) {
        s/^\s+//;           # entferne führende Leerzeichen
        s/\s+$//;           # entferne angehängte Leerzeichen
        s/(\w+)/\u\L$1/g;   # beginne jedes Wort mit einem Großbuchstaben
    }

Scheiben einer leeren Liste bleiben leere Listen. Daher gilt:

    @a = ()[1,0];           # @a hat keine Elemente
    @b = (@a)[0,1];         # @b hat keine Elemente
    @c = (0,1)[2,3];        # @c hat keine Elemente

Aber:

    @a = (1)[1,0];          # @a hat zwei Elemente
    @b = (1,undef)[1,0,2];  # @b hat drei Elemente

Dies vereinfacht das Schreiben von Schleifen, die terminieren wenn eine leere Liste zurückgegeben wird:

    while ( ($home, $user) = (getpwent)[7,0]) {
        printf "%-8s %s\n", $user, $home;
    }

Wie bereits früher in diesem Dokument bemerkt ist der skalare Wert einer Listenzuweisugn die Anzahl von Elementen auf der rechten Seite der Zuweisung. Die Nulliste enthält keine Elemente, so dass das Resultat 0 statt 2 wird, sobald die Passwortdatei vollständig ausgelesen ist.

Falls Du verwirrt bist, warum Du '@' statt '%' verwendest obwohl es sich um eine Hashscheibe handelt, betrachte es einmal so: Der Typ der Subskriptklammern (eckig oder geschweift) bestimmt, ob ein Array oder ein Hash betrachtet wird. Andererseits zeigt das führende Zeichen ('$' oder '@') vor dem Array oder Hash an, ob Du einen Singularwert (ein Skalar) oder einen Pluralwert (eine Liste) zurückbekommst.

Typeglobs und Dateihandles

Perl verwendet einen internen Datentyp, Typeglob genannt, um einen ganzen Symboltabelleneintrag zu speichern. Das Typenpräfix eines Typeglobs ist ein * , da er alle Typen repräsentiert. Früher war die Verwendung von Typeglobs der empfohlene Weg um Arrays oder Hashes per Referenz an eine Funktion zu übergeben, aber da uns nun echte Referenzen zur Verfügung stehen, wird das selten benötigt.

Der Hauptverwendungszweck von Typeglobs in modernem Perl ist es, Aliase für Symboltabelleneinträge zu erzeugen. Diese Zuweisung:

    *dies = *das;

macht $dies zu einem Synonym für $das, @dies zu einem Synonym für @das, %dies zu einem Synonym für %das, &dies zu einem Synonym für &das, usw. Viel sicherer ist es, eine Referenz zu verwenden. Diese Anweisung:

    local *Hier::blau = \$Dort::gruen;

macht $Hier::blau zeitweilig zu einem Alias für $Dort::gruen aber es macht nicht @Hier::blau zu einem Alias für @Dort::gruen oder $Hier::blau zu einem Alias für %Dort::gruen, usw. Siehe perlmod, Symbol Tables für weitere Beispiele hierfür. Auch wenn das alles seltsam erscheinen mag, so bildet es doch die Grundlage für das gesamte Import/Export-System für Module.

Eine weitere Verwendung für Typeglobs ist die Übergabe von Dateihandles an eine Funktion oder die Erstellung neuer Dateihandles. Wenn Du einen Typeglob verwenden möchtest, um ein Dateihandle abzuspeichern, mache es so:

    $fh = *STDOUT;

oder vielleicht als echte Referenz, so wie hier:

    $fh = \*STDOUT;

Siehe auch perlsub für Beispiele, wie diese Variablen dann als indirekte Dateihandles in Funktionen genutzt werden können.

Typeglobs bieten auch einen Weg um lokale Dateihandles mit Hilfe des Operators local() herzustellen. Diese bleiben bis zum Ende ihres umgebenden Blocks gültig, können aber zurückgegeben werden. Zum Beispiel:

    sub newopen {
        my $path = shift;
        local  *FH;  # local, nicht my!
        open   (FH, $path)          or  return undef;
        return *FH;
    }
    $fh = newopen('/etc/passwd');

Nun da es die *foo{DING} -Schreibweise gibt, werden Typeglobs nicht mehr so oft für Manipulationen an Dateihandles verwendet, obschon sie noch immer in Gebrauch sind, um nagelneue Datei- und Verzeichnishandles in Funktionen hinein oder aus ihnen heraus zu übergeben. Das liegt daran, dass *HANDLE{IO} nur funktioniert, wenn HANDLE bereits als Handle verwendet wurde. Mit anderen Worten, *FH muss verwendet werden um neue Einträge in der Symboltabelle anzulegen; *foo{DING} eignet sich dafür nicht. Benutze im Zweifelsfalle *FH .

Alle Funktionen, die in der Lage sind, Dateihandles zu erzeugen (open(), opendir(), pipe(), socketpair(), sysopen(), socket() und accept()) erzeugen automatisch ein anonymes Dateihandle, wenn das Handle, das ihnen übergeben wird, eine uninitialisierte Skalarvariable ist. Dadurch können Konstruktionen wie open(my $fh, ...) und open(local $fh, ...) verwendet werden unm Dateihandles zu erstellen, die praktischerweise automatisch geschlossen werden, sobald Ihr Geltungsbereich endet, sofern keine weiteren Referenzen auf sie existieren. Dies macht Typeglobs im großen und ganzen unnötig, wenn Dateien geöffnet werden, die an andere Stellen übergeben werden müssen, so wie im folgenden Beispiel:

    sub myopen {
        open my $fh, "@_"
             or die "Kann '@_' nicht öffnen: $!";
        return $fh;
    }

    {
        my $f = myopen("</etc/motd");
        print <$f>;
        # $f wird hier implizit geschlossen
    }

Beachte, dass das Ergebnis anders ist, wenn eine bereits initialisierte Skalarvariable verwendet wird: my $fh='zzz'; open($fh, ...) ist äquivalent zu open( *{'zzz'}, ...) . use strict 'refs' verbietet ein derartiges Vorgehen.

Eine weiterer Weg zur Erzeugung anonymer Dateihandles ist die Verwendung des Moduls Symbol oder des Modules IO::Handle? und seiner Verwandschaft. Diese Module haben den Vorteil, dass nicht während der Verwendung von local() mehrere Typen gleichen Namens verborgen werden. Siehe auch das Ende von perlfunc, open für ein Beispiel.

SIEHE AUCH

Siehe perlvar für eine Beschreibung der eingebauten Variablen von Perl und eine Diskussion erlaubter Variablennamen. Siehe perlref, perlsub und perlmod, Symbol Tables für weitere Behandlung des Themas Typeglobs und die *foo{DING} Syntax.

ÜBERSETZER

Thomas Chust < chust@web.de >


Kommentare:

-- ThomasChust - 13 Jan 2006
Topic revision: 2006-01-18, ThomasChust
 
Bitte die NutzungsBedingungen beachten.
Bei Vorschlägen, Anfragen oder Problemen mit dem PerlCommunityWiki bitten wir um WebBottomBarExample">Rückmeldung.