Suche…


Syntax

  • meine # Lexikalische Erklärung
  • unsere # globale erklärung
  • $ foo # Scalar
  • @foo # Array
  • $ # foo # Array Last-Index
  • % foo # Hash
  • $ {$ foo} # Scalar De-Reference
  • @ {$ foo} # Array-Referenz
  • $ # {$ foo} # Array-DeRef Last-Index
  • % {$ foo} # Hash-Referenz
  • $ foo [$ index] # Array wird indiziert
  • $ {$ foo} [$ index] # Array-Referenzierung und Indexierung.
  • $ foo -> [$ index] # Array-Referenzierung und Indexierung (vereinfacht)
  • $ foo {$ key} # Hashwert für Schlüssel
  • $ {$ foo} {$ key} # Hash Dereference und Wert für key
  • $ foo -> {$ key} # Hash Dereference und Wert für key (vereinfacht)
  • \ $ x # Verweis auf Skalar
  • \ @x # Verweis auf Array
  • \% x # Verweis auf Hash
  • = [] # Referenz auf anonymes Array (Inline)
  • = {} # Verweis auf anonymen Hash (Inline)

Scalars

Skalare sind der grundlegendste Datentyp von Perl. Sie sind mit dem Sigel $ und haben einen einzigen Wert von drei Typen:

  • eine Zahl ( 3 , 42 , 3.141 usw.)
  • eine Zeichenfolge ( 'hi' , "abc" usw.)
  • ein Verweis auf eine Variable (siehe andere Beispiele).
my $integer = 3;                      # number
my $string = "Hello World";           # string
my $reference = \$string;             # reference to $string

Perl konvertiert zwischen Zahlen und Strings im laufenden Betrieb , je nachdem, was ein bestimmter Operator erwartet.

my $number = '41';                    # string '41'
my $meaning = $number + 1;            # number  42
my $sadness = '20 apples';            # string '20 apples'
my $danger = $sadness * 2;            # number '40', raises warning

Wenn Sie eine Zeichenfolge in eine Zahl konvertieren, nimmt Perl so viele Ziffern wie möglich an der Vorderseite der Zeichenfolge an. Daher werden in der letzten Zeile 20 apples in 20 umgewandelt.

Je nachdem, ob Sie den Inhalt eines Skalars als eine Zeichenfolge oder eine Zahl behandeln möchten, müssen Sie unterschiedliche Operatoren verwenden. Mischen Sie sie nicht.

# String comparison                   # Number comparison
'Potato' eq 'Potato';                 42 == 42;
'Potato' ne 'Pomato';                 42 != 24;
'Camel'  lt 'Potato';                 41 < 42;
'Zombie' gt 'Potato';                 43 > 42;

# String concatenation                # Number summation
'Banana' . 'phone';                   23 + 19;

# String repetition                   # Number multiplication 
'nan' x 3;                            6 * 7;

Beim Versuch, Zeichenfolgenoperationen für Zahlen zu verwenden, werden keine Warnungen ausgegeben. Beim Versuch, Zahlenoperationen für nicht numerische Zeichenfolgen zu verwenden, wird versucht. Bitte beachten Sie, dass einige nicht-digitale Zeichenfolgen wie 'inf' , 'nan' , '0 but true' als Zahlen zählen.

Arrays

Arrays speichern eine geordnete Folge von Werten. Sie können über den Index auf den Inhalt zugreifen oder über ihn iterieren. Die Werte bleiben in der Reihenfolge, in der Sie sie eingegeben haben.

my @numbers_to_ten = (1,2,3,4,5,6,7,8,9,10); # More conveniently: (1..10)
my @chars_of_hello = ('h','e','l','l','o');
my @word_list = ('Hello','World');

# Note the sigil: access an @array item with $array[index]
my $second_char_of_hello = $chars_of_hello[1]; # 'e'

# Use negative indices to count from the end (with -1 being last)
my $last_char_of_hello = $chars_of_hello[-1];

# Assign an array to a scalar to get the length of the array
my $length_of_array = @chars_of_hello; # 5

# You can use $# to get the last index of an array, and confuse Stack Overflow
my $last_index_of_array = $#chars_of_hello; # 4

# You can also access multiple elements of an array at the same time
# This is called "array slice"
# Since this returns multiple values, the sigil to use here on the RHS is @
my @some_chars_of_hello = @chars_of_hello[1..3]; # ('H', 'e', 'l')
my @out_of_order_chars = @chars_of_hello[1,4,2]; # ('e', 'o', 'l')

# In Python you can say array[1:-1] to get all elements but first and last
# Not so in Perl: (1..-1) is an empty list. Use $# instead
my @empty_list = @chars_of_hello[1..-1];                           # ()
my @inner_chars_of_hello = @chars_of_hello[1..$#chars_of_hello-1]; # ('e','l','l')

# Access beyond the end of the array yields undef, not an error
my $undef = $chars_of_hello[6]; # undef    

Arrays sind veränderbar:

use utf8; # necessary because this snippet is utf-8
$chars_of_hello[1] = 'u';              #     ('h','u','l','l','o')
push @chars_of_hello, ('!', '!');      #     ('h','u','l','l','o','!','!')
pop @chars_of_hello;                   #     ('h','u','l','l','o','!')
shift @chars_of_hello;                 #         ('u','l','l','o','!')
unshift @chars_of_hello, ('¡', 'H');   # ('¡','H','u','l','l','o','!')
@chars_of_hello[2..5] = ('O','L','A'); # ('¡','H','O','L','A',undef,'!') whoops! 
delete $chars_of_hello[-2];            # ('¡','H','O','L','A',      '!')

# Setting elements beyond the end of an array does not result in an error
# The array is extended with undef's as necessary. This is "autovivification."
my @array;           # ()
my @array[3] = 'x';  # (undef, undef, undef, 'x')

Zum Schluss können Sie den Inhalt eines Arrays durchlaufen:

use v5.10; # necessary for 'say'
for my $number (@numbers_to_ten) {
  say $number ** 2;
}

Bei Verwendung als Boolesche Werte sind Arrays wahr, wenn sie nicht leer sind.

Hashes

Hashes können als Nachschlagetabellen verstanden werden. Sie können auf den Inhalt zugreifen, indem Sie für jeden einen Schlüssel angeben. Schlüssel müssen Strings sein. Wenn dies nicht der Fall ist, werden sie in Strings konvertiert.

Wenn Sie dem Hash einfach einen bekannten Schlüssel geben, liefert er Ihnen seinen Wert.

# Elements are in (key, value, key, value) sequence
my %inhabitants_of = ("London", 8674000, "Paris", 2244000);

# You can save some typing and gain in clarity by using the "fat comma"
# syntactical sugar. It behaves like a comma and quotes what's on the left.
my %translations_of_hello = (spanish => 'Hola', german => 'Hallo', swedish => 'Hej'); 

Beachten Sie im folgenden Beispiel die Klammern und das Siegel: Sie greifen mit $hash{key} auf ein Element von %hash , da der gewünschte Wert ein Skalar ist. Einige halten es für eine gute Praxis, den Schlüssel zu zitieren, während andere diesen Stil für visuell laut halten. Quoting ist nur für Schlüssel erforderlich, die mit Ausdrücken wie $hash{'some-key'} verwechselt werden können.

my $greeting = $translations_of_hello{'spanish'};

Während Perl standardmäßig versucht, Barewörter als Zeichenfolgen zu verwenden, kann der Modifikator + auch verwendet werden, um Perl mitzuteilen, dass der Schlüssel nicht interpoliert, sondern ausgeführt werden soll, wobei das Ergebnis der Ausführung als Schlüssel verwendet wird:

my %employee = ( name => 'John Doe', shift => 'night' );
# this example will print 'night'
print $employee{shift}; 

# but this one will execute [shift][1], extracting first element from @_,
# and use result as a key
print $employee{+shift};

Wie bei Arrays können Sie auf mehrere Hash-Elemente gleichzeitig zugreifen. Dies wird Hash-Slice genannt . Der resultierende Wert ist eine Liste. Verwenden Sie also das @ -Sigil:

my @words = @translations_of_hello{'spanish', 'german'}; # ('Hola', 'Hallo')

Iterieren über die Tasten eines Hash mit keys keys werden Elemente in zufälliger Reihenfolge zurück. Kombinieren Sie mit sort wenn Sie möchten.

for my $lang (sort keys %translations_of_hello) {
  say $translations_of_hello{$lang};
}

Wenn Sie die Schlüssel nicht wie im vorherigen Beispiel benötigen, geben values die Hashwerte direkt zurück:

for my $translation (values %translations_of_hello) {
  say $translation;
}

Sie können auch eine while - Schleife mit verwenden each über den Hash iterieren. Auf diese Weise erhalten Sie sowohl den Schlüssel als auch den Wert gleichzeitig, ohne dass ein separater Wertesuchvorgang ausgeführt wird. Sein Gebrauch wird jedoch abgelehnt , da each auf missbräuchliche Weise brechen kann.

# DISCOURAGED
while (my ($lang, $translation) = each %translations_of_hello) {
  say $translation;
}

Der Zugriff auf nicht gesetzte Elemente gibt undef zurück und nicht einen Fehler:

my $italian = $translations_of_hello{'italian'}; # undef

map und List Flattening können verwendet werden, um Hashes aus Arrays zu erstellen. Dies ist eine beliebte Methode, um eine 'Menge' von Werten zu erstellen, z. B. um schnell zu prüfen, ob ein Wert in @elems . Diese Operation benötigt normalerweise O (n) Zeit (dh proportional zur Anzahl der Elemente), kann jedoch in einer konstanten Zeit (O (1)) ausgeführt werden, indem die Liste in einen Hash umgewandelt wird:

@elems = qw(x y x z t);
my %set = map { $_ => 1 } @elems;   # (x, 1, y, 1, t, 1)
my $y_membership = $set{'y'};       # 1
my $w_membership = $set{'w'};       # undef

Dies erfordert eine Erklärung. Der Inhalt von @elems in eine Liste eingelesen, die von map verarbeitet wird. map akzeptiert einen Codeblock, der für jeden Wert seiner Eingabeliste aufgerufen wird. Der Wert des Elements kann in $_ . Unser Codeblock gibt zwei Listenelemente für jedes Eingabeelement zurück: $_ , das Eingabeelement und 1 , nur einen bestimmten Wert. Sobald Sie die Listenreduzierung berücksichtigt haben, führt dies dazu, dass die map { $_ => 1 } @elems qw(xyxzt) (x => 1, y => 1, x => 1, z => 1, t => 1) .

Wenn diese Elemente dem Hash zugewiesen werden, werden ungerade Elemente zu Hash-Schlüsseln und sogar Elemente zu Hash-Werten. Wenn ein Schlüssel mehrmals in einer Liste angegeben wird, die einem Hash zugewiesen werden soll, gewinnt der letzte Wert. Dadurch werden Duplikate effektiv verworfen.

Eine schnellere Möglichkeit, eine Liste in einen Hash zu verwandeln, verwendet die Zuweisung zu einem Hash-Slice. Es verwendet den x Operator, um die Liste der einzelnen Elemente (1) mit der Größe von @elems , sodass für jeden der Schlüssel im linken Bereich ein Wert von 1 vorhanden ist:

@elems = qw(x y x z t);
my %set;
@set{@elems} = (1) x @elems;

Die folgende Anwendung von Hashes nutzt auch die Tatsache aus, dass Hashes und Listen häufig austauschbar verwendet werden können, um benannte Funktionsargumente zu implementieren:

sub hash_args {
  my %args = @_;
  my %defaults = (foo => 1, bar => 0);
  my %overrides = (__unsafe => 0);
  my %settings = (%defaults, %args, %overrides);
}

# This function can then be called like this:
hash_args(foo => 5, bar => 3); # (foo => 5, bar => 3, __unsafe ==> 0)
hash_args();                   # (foo => 1, bar => 0, __unsafe ==> 0)
hash_args(__unsafe => 1)       # (foo => 1, bar => 0, __unsafe ==> 0)

Bei Verwendung als Boolesche Werte sind Hashwerte wahr, wenn sie nicht leer sind.

Skalarreferenzen

Eine Referenz ist eine skalare Variable (eine mit $ vorangestellt), die auf andere Daten „verweist“.

my $value     = "Hello";
my $reference = \$value;
print $value;     # => Hello
print $reference; # => SCALAR(0x2683310)

Um die Daten zu erhalten, auf die verwiesen wird, wird die Referenzierung aufgehoben.

say ${$reference};                  # Explicit prefix syntax
say $$reference;                    # The braces can be left out (confusing)
5.24.0

Neue Postfix-Dereferenzierungssyntax, standardmäßig ab Version 5.24 verfügbar

use v5.24;
say $reference->$*; # New postfix notation

Dieser "nicht referenzierte Wert" kann dann wie bei der ursprünglichen Variablen geändert werden.

${$reference} =~ s/Hello/World/;
print ${$reference};  # => World
print $value;         # => World

Eine Referenz ist immer wahr - auch wenn der Wert, auf den sie verweist, falsch ist (wie 0 oder "" ).

Möglicherweise möchten Sie eine Skalarreferenz, wenn:

  • Sie möchten eine Zeichenfolge an eine Funktion übergeben und diese Zeichenfolge für Sie ändern, ohne dass es sich dabei um einen Rückgabewert handelt.

  • Sie möchten explizit vermeiden, dass Perl den Inhalt einer großen Zeichenfolge an einem bestimmten Punkt Ihrer Funktionsübergabe implizit kopiert (besonders relevant bei älteren Perls ohne Schreib-Lese-Zeichenfolgen).

  • Sie möchten stringsähnliche Werte mit einer bestimmten Bedeutung von Strings unterscheiden, die Inhalt vermitteln, zum Beispiel:

    • Einen Dateinamen vom Dateiinhalt unterscheiden
    • Unterscheiden Sie zurückgegebenen Inhalt aus einer zurückgegebenen Fehlerzeichenfolge
  • Sie möchten ein einfaches Inside-out-out-Objektmodell implementieren, bei dem Objekte, die an aufrufenden Code übergeben werden, keine für den Benutzer sichtbaren Metadaten enthalten:

    our %objects;
    my $next_id = 0;
    sub new { 
       my $object_id = $next_id++;
       $objects{ $object_id } = { ... }; # Assign data for object
       my $ref = \$object_id;
       return bless( $ref, "MyClass" );
    }
    

Array-Referenzen

Arrayreferenzen sind Skalare ( $ ), die sich auf Arrays beziehen.

my @array = ("Hello"); # Creating array, assigning value from a list
my $array_reference = \@array;

Diese können wie folgt kurzer erstellt werden:

my $other_array_reference = ["Hello"];

Wenn Sie Array-Referenzen ändern / verwenden, müssen Sie diese zuerst dereferenzieren.

my @contents = @{ $array_reference };               # Prefix notation
my @contents = @$array_reference;                   # Braces can be left out
5.24.0

Neue Postfix-Dereferenzierungssyntax, standardmäßig ab Version 5.24 verfügbar

use v5.24;
my @contents = $array_reference->@*; # New postfix notation 

Beim Zugriff auf den Inhalt eines Arrays durch Index können Sie den -> syntaktischen Zucker verwenden.

my @array = qw(one two three);      my $arrayref = [ qw(one two three) ]
my $one = $array[0];                my $one = $arrayref->[0];

Im Gegensatz zu Arrays können Arrayrefs verschachtelt werden:

my @array = ( (1, 0), (0, 1) )  # ONE array of FOUR elements: (1, 0, 0, 1)
my @matrix = ( [1, 0], [0, 1] ) # an array of two arrayrefs
my $matrix = [ [0, 1], [1, 0] ] # an arrayref of arrayrefs
# There is no namespace conflict between scalars, arrays and hashes
# so @matrix and $matrix _both_ exist at this point and hold different values.

my @diagonal_1 = ($matrix[0]->[1], $matrix[1]->[0])     # uses @matrix
my @diagonal_2 = ($matrix->[0]->[1], $matrix->[1]->[0]) # uses $matrix
# Since chained []- and {}-access can only happen on references, you can
# omit some of those arrows.
my $corner_1 = $matrix[0][1];   # uses @matrix;
my $corner_2 = $matrix->[0][1]; # uses $matrix;  

Bei Verwendung als Boolean sind Verweise immer wahr.

Hash-Referenzen

Hashreferenzen sind Skalare, die einen Zeiger auf den Speicherort enthalten, der die Daten eines Hashes enthält. Da der Skalar direkt auf den Hash selbst verweist und an eine Subroutine übergeben wird, sind die am Hash vorgenommenen Änderungen nicht wie bei einem regulären Hash lokal, sondern global.

Lassen Sie uns zunächst untersuchen, was passiert, wenn Sie einen normalen Hash an eine Subroutine übergeben und dort ändern:

use strict;
use warnings;
use Data::Dumper;

sub modify
{
    my %hash = @_;

    $hash{new_value} = 2;

    print Dumper("Within the subroutine");
    print Dumper(\%hash);

    return;
}

my %example_hash = (
    old_value   => 1,
);

modify(%example_hash);

print Dumper("After exiting the subroutine");
print Dumper(\%example_hash);

Was in ... resultiert:

$VAR1 = 'Within the subroutine';
$VAR1 = {
          'new_value' => 2,
          'old_value' => 1
        };
$VAR1 = 'After exiting the subroutine';
$VAR1 = {
          'old_value' => 1
        };

Beachten Sie, dass der Hash nach dem Verlassen der Subroutine unverändert bleibt. Alle Änderungen daran waren lokal an der Modifikation subroutine, weil wir eine Kopie des Hashes übergeben haben, nicht den Hash selbst.

Im Vergleich: Wenn Sie eine Hashref übergeben, übergeben Sie die Adresse an den ursprünglichen Hash, sodass alle Änderungen, die innerhalb der Subroutine vorgenommen werden, am ursprünglichen Hash vorgenommen werden:

use strict;
use warnings;
use Data::Dumper;

sub modify
{
    my $hashref = shift;

    # De-reference the hash to add a new value
    $hashref->{new_value} = 2;

    print Dumper("Within the subroutine");
    print Dumper($hashref);

    return;
}

# Create a hashref
my $example_ref = {
    old_value   => 1,
};

# Pass a hashref to a subroutine
modify($example_ref);

print Dumper("After exiting the subroutine");
print Dumper($example_ref);

Dies führt zu:

$VAR1 = 'Within the subroutine';
$VAR1 = {
          'new_value' => 2,
          'old_value' => 1
        };
$VAR1 = 'After exiting the subroutine';
$VAR1 = {
          'new_value' => 2,
          'old_value' => 1
        };

Typeglobs, Typeglob-Refs, Dateihandles und Konstanten

Ein Typeglob *foo enthält Verweise auf den Inhalt globaler Variablen mit diesem Namen: $foo , @foo , $foo &foo usw. Sie können darauf wie ein Hash zugreifen und die Manipulation der Symboltabellen direkt zuweisen (böse!).

use v5.10; # necessary for say
our $foo = "foo";
our $bar;
say ref *foo{SCALAR};     # SCALAR
say ${ *foo{SCALAR} };    # bar
*bar = *foo;
say $bar;                 # bar
$bar = 'egg';
say $foo;                 # egg

Typeglobs werden häufiger beim Umgang mit Dateien behandelt. open erzeugt beispielsweise einen Verweis auf ein Typeglob, wenn Sie aufgefordert werden, ein nicht globales Dateihandle zu erstellen:

use v5.10; # necessary for say
open(my $log, '> utf-8', '/tmp/log') or die $!; # open for writing with encoding
say $log 'Log opened';

# You can dereference this globref, but it's not very useful.
say ref $log;                   # GLOB
say (*{$log}->{IO} // 'undef'); # undef

close $log or die $!;

Typeglobs können auch verwendet werden, um globale schreibgeschützte Variablen zu erstellen, obwohl use constant use breiter verwendet wird.

# Global constant creation
*TRUE = \('1');
our $TRUE;
say $TRUE;  # 1
$TRUE = ''; # dies, "Modification of a read-only value attempted"

# use constant instead defines a parameterless function, therefore it's not global,
# can be used without sigils, can be imported, but does not interpolate easily.
use constant (FALSE => 0);
say FALSE;        # 0
say &FALSE;       # 0
say "${\FALSE}";  # 0 (ugh)
say *FALSE{CODE}; # CODE(0xMA1DBABE)

# Of course, neither is truly constant when you can manipulate the symbol table...
*TRUE = \('');
use constant (EVIL => 1);
*FALSE = *EVIL;

Sigils

Perl hat eine Reihe von Siegeln:

$scalar = 1; # individual value
@array = ( 1, 2, 3, 4, 5 ); # sequence of values
%hash = ('it', 'ciao', 'en', 'hello', 'fr', 'salut'); # unordered key-value pairs
&function('arguments'); # subroutine
*typeglob; # symbol table entry

Diese sehen wie Siegel aus, sind aber nicht:

\@array; # \ returns the reference of what's on the right (so, a reference to @array)
$#array; # this is the index of the last element of @array

Sie können nach dem Siegel eine Zahnspange verwenden, wenn Sie dazu geneigt sind. Gelegentlich verbessert dies die Lesbarkeit.

say ${value} = 5;

Während Sie verschiedene Sigels verwenden, um Variablen verschiedener Typen zu definieren, können Sie auf dieselbe Variable auf verschiedene Arten zugreifen, je nachdem, welche Sigils Sie verwenden.

%hash;            # we use % because we are looking at an entire hash
$hash{it};        # we want a single value, however, that's singular, so we use $
$array[0];        # likewise for an array. notice the change in brackets.
@array[0,3];      # we want multiple values of an array, so we instead use @
@hash{'it','en'}; # similarly for hashes (this gives the values: 'ciao', 'hello')
%hash{'it','fr'}; # we want an hash with just some of the keys, so we use %
                  # (this gives key-value pairs: 'it', 'ciao', 'fr', 'salut')

Dies gilt insbesondere für Referenzen. Um einen referenzierten Wert zu verwenden, können Sie Sigile miteinander kombinieren.

my @array = 1..5;                    # This is an array
my $reference_to_an_array = \@array; # A reference to an array is a singular value
push @array, 6;                      # push expects an array
push @$reference_to_an_array, 7;     # the @ sigil means what's on the right is an array
                                     # and what's on the right is $reference_to_an_array
                                     # hence: first a @, then a $

Hier ist eine vielleicht weniger verwirrende Art, darüber nachzudenken. Wie wir bereits gesehen haben, können Sie mit Klammern rechts von einem Siegel wickeln. Sie können sich also @{} als etwas vorstellen, das eine Arrayreferenz annimmt und Ihnen das referenzierte Array liefert.

# pop does not like array references
pop $reference_to_an_array; # ERROR in Perl 5.20+
# but if we use @{}, then...
pop @{ $reference_to_an_array }; # this works!

@{} Akzeptiert tatsächlich einen Ausdruck:

my $values = undef;
say pop @{ $values };       # ERROR: can't use undef as an array reference
say pop @{ $values // [5] } # undef // [5] gives [5], so this prints 5

... und der gleiche Trick funktioniert auch für andere Siegel.

# This is not an example of good Perl. It is merely a demonstration of this language feature
my $hashref = undef;
for my $key ( %{ $hashref // {} } ) {
  "This doesn't crash";
}

... aber wenn das "Argument" für ein Siegel einfach ist, können Sie die Klammern weglassen.

say $$scalar_reference;
say pop @$array_reference;
for keys (%$hash_reference) { ... };

Dinge können übermäßig extravagant werden. Das funktioniert aber bitte Perl verantwortungsvoll.

my %hash = (it => 'ciao', en => 'hi', fr => 'salut');
my $reference = \%hash;
my $reference_to_a_reference = \$reference;

my $italian = $hash{it};                              # Direct access 
my @greets = @$reference{'it', 'en'};                 # Dereference, then access as array
my %subhash = %$$reference_to_a_reference{'en', 'fr'} # Dereference ×2 then access as hash

Für die meisten normalen Anwendungen können Sie Namen von Unterprogrammen ohne Siegel verwenden. (Variablen ohne Siegel werden normalerweise als "Barewords" bezeichnet.) Das & Sigil ist nur in einer begrenzten Anzahl von Fällen nützlich.

  • Einen Verweis auf eine Subroutine machen:

    sub many_bars { 'bar' x $_[0] }
    my $reference = \&many_bars;
    say $reference->(3); # barbarbar
    
  • Aufruf einer Funktion, wobei der Prototyp ignoriert wird.

  • Kombiniert mit goto als etwas seltsamer Funktionsaufruf, bei dem der aktuelle Anrufrahmen durch den Anrufer ersetzt wird. Stellen Sie sich den linux exec() API-Aufruf vor, aber für Funktionen.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow