Perl Language
variabler
Sök…
Syntax
- min # Lexical deklaration
- vår # globala deklaration
- $ foo # Scalar
- @Foo # Array
- $ # foo # Array Last-Index
- % foo # Hash
- $ {$ foo} # Scalar De-Reference
- @ {$ foo} # Array De-Reference
- $ # {$ foo} # Array-DeRef Last-Index
- % {$ foo} # Hash-referens
- $ foo [$ index] # Array indexeras
- $ {$ foo} [$ index] # Array De-Reference och indexeras.
- $ foo -> [$ index] # Array De-Reference och bli indexerad (förenklad)
- $ foo {$ key} # Hash får värde för nyckel
- $ {$ foo} {$ key} # Hash Dereference och få värde för nyckeln
- $ foo -> {$ key} # Hash Dereference och få värde för nyckel (förenklad)
- \ $ x # Hänvisning till skalar
- \ @x # Hänvisning till Array
- \% x # Hänvisning till Hash
- = [] # Hänvisning till anonym anordning (inline)
- = {} # Hänvisning till Anonym Hash (inline)
skalärer
Scalars är Perls mest grundläggande datatyp. De är markerade med sigil $
och har ett värde av en av tre typer:
- ett nummer (
3
,42
,3.141
, etc.) - en sträng (
'hi'
,"abc"
, etc.) - en hänvisning till en variabel (se andra exempel).
my $integer = 3; # number
my $string = "Hello World"; # string
my $reference = \$string; # reference to $string
Perl konverterar mellan siffror och strängar i farten , baserat på vad en viss operatör förväntar sig.
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
När man konverterar en sträng till ett nummer tar Perl så många siffror från framsidan av en sträng som det kan - varför 20 apples
konverteras till 20
i den sista raden.
Baserat på om du vill behandla innehållet i en skalar som en sträng eller ett nummer, måste du använda olika operatörer. Blanda inte dem.
# 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;
Att försöka använda strängoperationer på nummer kommer inte att ge varningar; att försöka använda nummeroperationer på icke-numeriska strängar kommer. Var medveten om att vissa icke-siffriga strängar som 'inf'
, 'nan'
, '0 but true'
räknas som siffror.
arrayer
Matriser lagrar en ordnad sekvens av värden. Du kan komma åt innehållet genom index eller iterera över dem. Värdena förblir i den ordning du fyllde in dem.
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
Matriser är muterbara:
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')
Slutligen kan du slinga över innehållet i en matris:
use v5.10; # necessary for 'say'
for my $number (@numbers_to_ten) {
say $number ** 2;
}
När de används som booleaner, är matriser sanna om de inte är tomma.
hashes
Hashar kan förstås som uppslagstabeller. Du kan komma åt dess innehåll genom att ange en nyckel för var och en av dem. Nycklar måste vara strängar. Om de inte är det, kommer de att konverteras till strängar.
Om du ger hash helt enkelt en känd nyckel kommer den att tjäna dig som dess värde.
# 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');
I följande exempel noterar du parenteserna och sigil: du får åtkomst till ett element av %hash
med $hash{key}
eftersom värdet du vill ha är en skalar. Vissa anser att det är bra att citera nyckeln medan andra tycker att den här stilen är visuellt bullrig. Citering krävs endast för nycklar som kan misstas för uttryck som $hash{'some-key'}
my $greeting = $translations_of_hello{'spanish'};
Medan Perl som standard kommer att försöka använda barewords som strängar, kan +
modifierare också användas för att indikera för Perl att nyckeln inte ska interpoleras utan exekveras med resultatet av exekveringen som en nyckel:
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};
Liksom med matriser kan du komma åt flera hashelement samtidigt. Detta kallas en hashskiva . Det resulterande värdet är en lista, så använd @
sigil:
my @words = @translations_of_hello{'spanish', 'german'}; # ('Hola', 'Hallo')
Iterera över nycklarna till en hash med keys
keys
kommer att återvända objekt i en slumpmässig ordning. Kombinera med sort
om du vill.
for my $lang (sort keys %translations_of_hello) {
say $translations_of_hello{$lang};
}
Om du inte faktiskt behöver knapparna som i föregående exempel returnerar values
hashens värden direkt:
for my $translation (values %translations_of_hello) {
say $translation;
}
Du kan också använda en stundslinga med each
att iterera över hash. På det här sättet får du både nyckeln och värdet samtidigt utan en separat värdesökning. Användningen avskaffas dock, eftersom each
kan bryta på felaktiga sätt.
# DISCOURAGED
while (my ($lang, $translation) = each %translations_of_hello) {
say $translation;
}
Åtkomst till bortkopplade element returnerar undef, inte ett fel:
my $italian = $translations_of_hello{'italian'}; # undef
map
och listutjämning kan användas för att skapa hashes ur matriser. Detta är ett populärt sätt att skapa en 'uppsättning' av värden, t.ex. att snabbt kontrollera om ett värde finns i @elems
. Denna operation tar vanligtvis O (n) -tid (dvs. proportionell mot antalet element) men kan göras i konstant tid (O (1)) genom att förvandla listan till en hash:
@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
Detta kräver lite förklaring. Innehållet i @elems
läses in i en lista som bearbetas med en map
. map
accepterar ett kodblock som blir uppmanat för varje värde i dess inmatningslista; värdet på elementet är tillgängligt för användning i $_
. Vårt kodblock returnerar två listelement för varje ingångselement: $_
, ingångselementet och 1
, bara något värde. När du redogör för utjämning av listan blir resultatet att map { $_ => 1 } @elems
förvandlar qw(xyxzt)
till (x => 1, y => 1, x => 1, z => 1, t => 1)
.
När dessa element tilldelas hash, blir udda element hashnycklar och till och med element blir hashvärden. När en nyckel anges flera gånger i en lista som ska tilldelas en hash, vinner det sista värdet. Detta kastar effektivt duplikat.
Ett snabbare sätt att förvandla en lista till en hash använder tilldelning till en hashskiva. Den använder x
operatören att multiplicera den enkelelementlistan (1)
av storleken på @elems
, så det finns en 1
värde för var och en av nycklarna i slice på vänster sida:
@elems = qw(x y x z t);
my %set;
@set{@elems} = (1) x @elems;
Följande tillämpning av hashes utnyttjar också det faktum att hashes och listor ofta kan användas omväxlande för att implementera namngivna funktionsarg:
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)
När hash används om booleaner är hash sanna om de inte är tomma.
Scalar Referenser
En referens är en skalärvariabel (en förinställd av $
) som "hänvisar till" vissa andra data.
my $value = "Hello";
my $reference = \$value;
print $value; # => Hello
print $reference; # => SCALAR(0x2683310)
För att få informationen som hänvisas till hänvisar du till den.
say ${$reference}; # Explicit prefix syntax
say $$reference; # The braces can be left out (confusing)
Ny postfix dereference-syntax, tillgänglig som standard från v5.24
use v5.24;
say $reference->$*; # New postfix notation
Detta "de-refererade värde" kan sedan ändras som om det var den ursprungliga variabeln.
${$reference} =~ s/Hello/World/;
print ${$reference}; # => World
print $value; # => World
En referens är alltid sanningen - även om värdet den hänvisar till är falska (som 0
eller ""
).
Du kanske vill ha en skalreferens om:
Du vill vidarebefordra en sträng till en funktion och låta den ändra strängen för dig utan att det är ett returvärde.
Du vill uttryckligen undvika att Perl implicit kopierar innehållet i en stor sträng vid någon tidpunkt när din funktion passerar (särskilt relevant för äldre Perls utan kopierings-på-skriva strängar)
Du vill disambiguera strängliknande värden med specifik betydelse, från strängar som förmedlar innehåll, till exempel:
- Ta bort ett filnamn från filinnehållet
- Oavgränsat returnerat innehåll från en returnerad felsträng
Du vill implementera en lätt inifrån och ut objektmodell där objekt som överlämnas till samtalskod inte innehåller användarsynliga metadata:
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-referenser
Array-referenser är skalar ( $
) som hänvisar till Arrays.
my @array = ("Hello"); # Creating array, assigning value from a list
my $array_reference = \@array;
Dessa kan skapas mer kortfattade på följande sätt:
my $other_array_reference = ["Hello"];
För att ändra / använda matrisreferenser krävs att du först ska göra dem.
my @contents = @{ $array_reference }; # Prefix notation
my @contents = @$array_reference; # Braces can be left out
Ny postfix dereference-syntax, tillgänglig som standard från v5.24
use v5.24;
my @contents = $array_reference->@*; # New postfix notation
När du öppnar ett arrayref-innehåll med index kan du använda ->
syntaktiskt socker.
my @array = qw(one two three); my $arrayref = [ qw(one two three) ]
my $one = $array[0]; my $one = $arrayref->[0];
Till skillnad från matriser kan matriser kapslas:
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;
När de används som booleska är referenser alltid sanna.
Hash-referenser
Hash-referenser är skalar som innehåller en pekare till minnesplatsen som innehåller data från en hash. Eftersom skalan pekar direkt på hash själv, när den överförs till en subroutine, är förändringar som görs på hash inte lokala för subroutinen som med en vanlig hash, utan är istället globala.
Låt oss först undersöka vad som händer när du skickar en normal hash till en subrutin och ändrar den där inne:
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);
Vilket resulterar i:
$VAR1 = 'Within the subroutine';
$VAR1 = {
'new_value' => 2,
'old_value' => 1
};
$VAR1 = 'After exiting the subroutine';
$VAR1 = {
'old_value' => 1
};
Lägg märke till att hash förblir oförändrat när vi har lämnat subrutinen. alla förändringar av det var lokala för modifiera subroutinen, eftersom vi skickade en kopia av hash, inte hash själv.
Som jämförelse, när du passerar en hashref, skickar du adressen till den ursprungliga hash, så alla ändringar som görs inom subroutinen kommer att göras till den ursprungliga hash:
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);
Detta kommer att resultera i:
$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, filhandtag och konstanter
En typeglob *foo
innehåller referenser till innehållet i globala variabler med det namnet: $foo
, @foo
, $foo
, &foo
, etc. Du kan komma åt det som en hash och tilldela för att manipulera symboltabellerna direkt (onda!).
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
Typglobs hanteras oftare vid hantering av filer. open
, till exempel, producerar en referens till en typglob när du blir ombedd att skapa en icke-global filhandtag:
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 kan också användas för att skapa globala skrivskyddsvariabler, även om use constant
är i bredare användning.
# 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;
sigill
Perl har ett antal siglar:
$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
Dessa ser ut som sigils, men är inte:
\@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
Du kan använda hängslen efter sigilen om du skulle vara så benägen. Ibland förbättrar detta läsbarheten.
say ${value} = 5;
Medan du använder olika sigils för att definiera variabler av olika typer, kan du komma åt samma variabel på olika sätt baserat på vilka sigils du använder.
%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')
Detta gäller särskilt referenser. För att använda ett referensvärde kan du kombinera sigiler tillsammans.
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 $
Här är ett kanske mindre förvirrande sätt att tänka på. Som vi såg tidigare kan du använda hängslen för att linda in vad som är till höger om en sigil. Så du kan tänka på @{}
som något som tar en matrisreferens och ger dig den refererade arrayen.
# 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!
Som det visar sig accepterar @{}
ett uttryck:
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
... och samma trick fungerar också för andra sigils.
# 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";
}
... men om "argumentet" till en sigil är enkelt kan du lämna hängslen borta.
say $$scalar_reference;
say pop @$array_reference;
for keys (%$hash_reference) { ... };
Saker kan bli alltför extravaganta. Det här fungerar, men vänligen Perl ansvarsfullt.
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 mest normalt bruk kan du bara använda subroutine-namn utan en sigil. (Variabler utan sigil kallas vanligtvis "barewords".) &
Sigil är bara användbar i ett begränsat antal fall.
Hänvisning till en subrutin:
sub many_bars { 'bar' x $_[0] } my $reference = \&many_bars; say $reference->(3); # barbarbar
Anropar en funktion som ignorerar dess prototyp.
Kombinerat med goto, som ett något konstigt funktionssamtal som har den aktuella samtalsramen ersatt med den som ringer. Tror att Linux
exec()
API-samtalet, men för funktioner.