Perl jämförelseoperatorer. Jämförelse av skalärer i Perl. Stjärnskruvmejsel - återställ variabeln till '' efter tillstånd

Intressanta icke-uppenbara Perl-konstruktioner övervägs.

Som du vet är programmeringsspråket Perl väldigt uttrycksfullt och har i sin arsenal många verktyg som gör att du kan uttrycka programmerarens avsikter i koden på många helt olika sätt. Dessutom, på grund av den ganska knepiga syntaxen, kan vissa kombinationer av operatorer leda till intressanta effekter.

Vissa saker kan också användas på ett icke-standardiserat sätt för att uppnå önskat resultat. Denna åtgärd kallas ibland "att köra spikar med ett mikroskop." Det är precis vad vi kommer att göra.

  • Beteendet för uttalandena i den här artikeln kan variera från version till version av Perl.
  • Dessa operatörer är sannolikt inte avsedda att användas i produktionen.
  • De flesta av dessa operatörer skapades av människor som tycker om att utforska sitt favoritspråk.
  • Allt som anges nedan och kallas operatörer är faktiskt inte dem.

Operatör "Venus"

0+ +0

namn

Operatören fick sitt namn från dess yttre likhet med symbolen för Venus.

Vad gör han?

Konverterar argumentet till vänster eller höger, beroende på version, till en numerisk form. Till exempel:

Skriv ut 0+ "23a"; skriv ut 0+ "3.00"; print 0+ "1.2e3"; skriv ut 0+ "42 EUR"; skriv ut 0+ "två cent";

Resultat:

23 3 1200 42 0

Denna operatör är en sträcka Burk använd i dina projekt, men du bör inte glömma att ur Perl-synpunkt är siffror till exempel: 0 men sant 0E0 och några mer knepiga konstanter. En annan sak att notera är att 0+ är standardmetoden som används för numerisk konvertering när man använder överbelastning.

"Sköldpadda", "Pam" eller "Supermarket Trolley"

@{}

namn

Operatören fick sitt namn på grund av dess yttre likhet med en sköldpadda eller en barnvagn. Känd för att ha upptäckts av Larry Wall 1994.

Vad gör han?

Detta är den så kallade containeroperatorn, som låter dig interpolera en array inuti en sträng. De resulterande arrayelementen kommer att separeras av innehållet i variabeln $".

Hur fungerar det?

Innehållet tvingas först utvärderas i listsammanhang, sedan omedelbart bortreferens (@( )).

Skriv ut "Testa jag är @([ die()])"; skriv ut "här";

Resultat:

Död på demo.pl linje 1.

Denna operator kan användas för att exekvera godtycklig kod i strängar när interpolering sker. Du kan till exempel använda den för att göra vissa saker enklare, som att bygga SQL-frågor:

Min $sql = "VÄLJ ID, namn, lön FRÅN anställd WHERE id IN (@([ nycklar %anställd ])) SQL ";

men vinsten av ett par rader kod motiverar inte de potentiella säkerhetsproblemen (en god praxis i SQL är att använda så kallade bindvariabler, som kommer att ersättas under förberedelsen). På grund av att det inte är självklart är det inte värt att använda operatören i produktionen, det finns potentiell sårbarhet och minskad läsbarhet.

Bang Bang

!!

Denna operatör användes när Perl inte fanns, den användes ofta av C-programmerare.

Hur fungerar det?

Den här operatorn gör följande elementära sak - dubbel negation, vars essens kommer ner till en boolesk omvandling. Kom ihåg att det inte finns några booleska typer i Perl.

Min $true = !! "en sträng"; min $false = !! undef;

Som ett resultat innehåller $true 1 och $false innehåller den tomma strängen "" . Denna operator kan användas för att kontrollera om det finns ett värde i till exempel en hashreferens, t.ex.

!! $hash->(värde) eller die("Saknat värde");

Mask

~~

Namn?

Den liknar enkelt och opretentiöst en mallarv och många maskar också.

Hur fungerar det?

~~-operatorn ser väldigt lik smart matchning, men det är inte för att den är det unär operatör.

En unär operation är en operation på en operand

Medan smart matchning är en binär operation (en operation på två operander, till exempel addition).

Vad gör han?

Bara det skalära nyckelordet förkortat med fyra (!) tecken.

Perl -Esay~~lokal tid tis 30 jul 17:43:16 2013

Funktionsprincipen för operatören liknar Bang Bang (!!) operatören, men skiljer sig genom att i Perl är operatören operatörsberoende. Du kan ta reda på mer genom att titta på dokumentationen om bitvisa operationer i Perl. Du kan använda den här operatorn, men du bör vara försiktig, det är okänt hur den kommer att bete sig på alla versioner av Perl.

Mask-på-sticka

-~ ~-

Detta är en operatör för ökning/minskning med hög prioritet. -~ ökar bara siffror som mindre noll, och ~ - minskar siffror Mer noll

Företrädet för denna operator är högre än aritmetiska operatorer förutom exponentiering (**). Till exempel:

$y = ~-$x * 4;

Det kommer att köras identiskt:

$y = ($x-1)*4;

Men inte som:

$y = ($x * 4) -1

För att dessa operatorer ska fungera med osignerade datatyper måste du använda heltalspragman (använd heltal). Denna operatör fungerar ganska bra och kan användas i produktionen, men du bör inte göra detta, eftersom på icke-standardiserade arkitekturer kan dess beteende skilja sig från ovanstående. Jag skulle vilja prova det i aktion på ARM-plattformar, men författaren till artikeln har inte en sådan enhet.

Rymdstation

-+-

Öppnades av Alistair McGlinchy 2005.

Den här operatorn utför en högprioriterad cast till numerisk form och liknar i beteende som Venus-symboloperatorn, men skiljer sig på följande sätt. Venus-operatören (0+ eller +0) använder binär operator + , medan "Rymdstation" använder tre unära operatorer sammanlänkade och har därför högre prioritet.

Det är också värt att komma ihåg att denna operator har lägre prioritet än de sammanlänkade operatorerna * och x . Principerna för dess funktion kan illustreras av följande exempel, där vi kommer att försöka skriva ut den konverterade till numeriska formen "20GBP" tre gånger:

Felaktigt, eftersom returnerar den konverterade versionen av strängen "20GBP20GBP20GBP" :

Skriv ut 0+ "20GBP" x 3; #20

Felaktigt, eftersom motsvarar (skriv ut "20") x 3:

Print(0+ "20GBP") x 3; #20

Korrekt, men väldigt lång, väldigt Lisp-liknande:

Print((0 + "20GBP") x 3); #202020

Det stämmer - med "rymdstationen"-operatorn:

Skriv ut -+- "20GBP" x 3; #202020

Men eftersom unary minus - och unary + ersätt helt enkelt resultatet av strängen med dess värde, sedan denna operator ska inte arbeta med följande typ av strängar:

  • Med de som börjar med - .
  • Med de som börjar med inte numeriskt symbol.

Medan Venus-operatören fungerar i alla dessa fall, men har lägre prioritet.

Get- eller Saturnusoperatör

=()=

Vad gör han?

Denna operator introducerar en listkontext till höger om den och returnerar antalet element till vänster.

Hur fungerar det?

En lista i skalär kontext returnerar antalet element. Det spelar ingen roll hur många element av dem som tilldelades variablerna. I ett sådant fall kommer den högra sidan av uttrycket att kastas till den tomma listan och sedan kasseras.

$n =()= /ord1|ord2|ord3/g; $n =()= "abababab" =~ /a/; # $n = 1 $n =()= "abababab" =~ /a/g; # $n = 4

Dessutom är denna operatör container (!), vilket gör att du enkelt kan "dra" resultatet av höger sida in i den. Det betyder att vi kan göra följande:

$n =($b)= "abababab" =~ /a/g; # $n = 4; $b = "a" $n =(@c)= "abababab" =~ /a/g; # $n = 4; @c = qw(a a a a)

Följande "luriga" exempel på dess användning verkar ha merit, men det finns en annan hemlig operatör som kan göra samma sak.

Låt oss säga att vi vill veta hur många delar som delas upp en sträng i, men vi är inte intresserade av själva elementen, kanske är det vettigt att prova något sånt här:

Min $count = split /:/, $string;

Det här exemplet kommer att returnera det nödvändiga numret, men svär på:

Användning av implicit split till @_ är utfasad

För att lösa detta problem kan vi använda den här operatorn och skriva något så här:

Min $count =()= split /:/, $string;

Vilket inte kommer att orsaka en varning, men kommer alltid att returnera 1 eftersom split aldrig delar inte strängen i fler delar än nödvändigt. I sin tur ser kompilatorn försöket att spara i () som ett uttalande att vi inte behöver dessa element och kommer att returnera en oförändrad sträng, som kommer att reduceras till en lista med ett element.

Det finns två möjliga lösningar.

Den första är att vi kan förhindra kompilatorn från att optimera split() genom att specificera med -1 att vi vill ha ett oändligt antal bitar av strängen:

Min $count =()= split /:/, $string, -1;

Eller använd en annan hemlig operatör, "sköldpadda":

Min $count = @([ split /:/, $string ]);

Drake

~~<>

I själva verket är denna operatör bara en kombination av Worm och<>. Det tillhandahåller ett skalärt sammanhang för operationen readline(), men det är bara användbart i en lista.

Utsmyckat tveeggat svärd

<> m;

Denna hemliga operatör ger flerradskommentarer och inget mer. Användningsexempel:

<> Använd den hemliga operatorn på föregående rad. Lägg dina kommentarer här. Många och många kommentarer. Du kan till och med använda tomma rader. Avsluta med ett enda m;

Men du bör ta hänsyn till det faktum att den här kommentaren bara är en sträng omsluten av dubbla citattecken, och därför kan ha vissa biverkningar.

Skruvmejseloperatörer

Upptäckt av Dmitry Karasik när han letade efter operatörer baserat på! . Liksom skruvmejslar finns dessa operatörer i fyra huvudtyper, men med olika handtagslängder:

Rak skruvmejsel - ger minskning enligt tillståndet:

$x -=!! $y # $x-- om $y; $x -=! $y # $x-- om inte $y;

Stjärnskruvmejsel - öka efter tillståndet:

$x +=!! $y; # $x++ om $y; $x +=! $y; # $x++ om inte $y;

Stjärnskruvmejsel - återställ variabeln till 0 enligt villkoret:

$x *=!! $y; # $x = 0 om inte $y; $x *=! $y; # $x = 0 om $y;

Stjärnskruvmejsel - återställ variabeln till '' efter villkor:

$x x=!! $y; # $x = "" om inte $y; $x x=! $y; # $x = "" om $y;

Företagsoperatör

()x!!

Ganska ofta finns det ett behov av att lägga till ett element i en lista baserat på ett villkor. Detta kan göras på följande sätt:

Min @shopping_list = ("bröd", "mjölk"); push @shopping_list, "äpplen" om $skåp(äpplen)< 2; push @shopping_list, "bananas" if $cupboard{bananas} < 2; push @shopping_list, "cherries" if $cupboard{cherries} < 20; push @shopping_list, "tonic" if $cupboard{gin};

I den här delen kommer vi att prata om villkorliga uttalanden och loopar.

Villkorliga uttalanden

Låt oss som alltid börja genast med exempel.

$a = skift ;
if ($a > 10) (
skriv ut "a > 10 \n";
}

Denna konstruktion borde vara smärtsamt bekant för programmerare på C-liknande språk, så det finns inte mycket att kommentera här. Låt mig bara säga att, till skillnad från C, kan du inte utelämna de lockiga hängslen här. Mer exakt, det finns ett sätt, men mer om det nedan. Om-annat och om-annat-om-...-konstruktionerna i Perl ser ut så här:

$a = skift ;
if ($a > 10) (
skriv ut "a > 10 \n";
) annat (
skriv ut "a<= 10\n";
}

if ($a > 0 ) (
# göra någonting
) elsif ($a == 0 ) (
# göra någonting
) annat (
# gör något annat
}

I allmänhet är allt som vi förväntar oss med ett undantag. Det finns inget "annat om" i Perl - istället ska du använda elsif och bara det. Elsif kan upprepas flera gånger, annat är inte nödvändigt, och lockiga hängslen kan inte utelämnas.

Till skillnad från andra programmeringsspråk tillhandahåller Perl också ett unless-uttalande. Följande två kodbitar gör samma sak:

om inte ($a == 0 ) (
# "...om inte a är noll"
...
}

if ($a != 0 ) (
# det samma
# ...
}

Unless kan användas i kombination med elsif och annat, men det finns ingen "elsunless" i Perl.

Perl har förmågan att minska mängden kod om bara en rad kod behöver exekveras när ett villkor är uppfyllt. Följande exempel gör samma sak:


if ($a > $b) (
utgång 1 ;
}


om inte ($b == $c ) (
utgång 2;
}

# om villkoret är sant, avsluta skriptet med kod 1
avsluta 1 om ($a > $b) ;
# om b == c, fortsätt skriptkörningen
avsluta 2 om inte ($b == $c );

Du behöver dock inte använda parenteser i det sista exemplet:

# om villkoret är sant, avsluta skriptet med kod 1
avsluta 1 om $a > $b ;

Om du skriver i Java/PHP eller ett annat C-liknande språk kommer denna konstruktion med största sannolikhet att vara ovanlig för dig, men i praktiken är det riktigt bekvämt. På ryska brukar vi också säga "avsluta programmet om ...", och inte "om ... då ...".

Precis som C/C++ och PHP har Perl ternär operatör?:. Det fungerar på samma sätt som om-else-konstruktionen, bara inuti uttryck:

if ($a > $b) (
$a = $a / $b ;
) annat (
$a = $b / $a ;
}

# liknande kod med frågeteckenoperatorn
# en rad kod istället för fem
$a = $a > $b ? $a / $b: $b / $a ;

Jag skulle också vilja säga några ord om jämförelseoperatörer. Jämförelseoperatörer i Perl-språket är de uppdelade i två grupper - de som jämför siffror och jämför strängar.

Som du kanske minns kan skalärer i Perl tolkas som antingen strängar eller siffror. Till exempel är siffran 123 större än siffran 45, men strängen "123" är mindre än strängen "45". Detta är vad som krävde flera grupper av jämförelseoperatörer. Strängjämförelse i Perl görs på samma sätt som i andra moderna programmeringsspråk, så jag hoppas att detta inte väcker några frågor.

Slingor för, foreach, while/tills, do..while/tills

For-loopen är mycket bekant för alla programmerare:

# skriv ut strängen "0 1 2 3 4"
för ($i = 0; $i< 5 ; $i ++ ) {
skriv ut "$i" ;
}

Följande är skrivet inom parentes separerade med semikolon:

  1. Kod exekveras innan loopen börjar.
  2. Tillståndet testas innan början(och inte i slutet, som många tror) av varje iteration. Om det är falskt slutar slingan.
  3. Kod exekveras efter varje iteration.

Som i fallet med villkorliga uttalanden kan du inte utelämna lockiga klammerparenteser i slingor (det finns också en speciell notation för detta - se nedan).

Foreach loop bör vara mycket bekant för PHP-programmerare:

@arr = (0, 1, 2, 3, 4);
# skriv ut strängen "0 1 2 3 4"
foreach $i (@arr ) (
skriv ut "$i" ;
}

Broppen i foreach loop exekveras för varje element i arrayen som anges inom parentes. En viktig egenskap hos foreach är i variabeln $i inte kopieras arrayelement @arr, som många tror. Variabeln $i i slingans kropp är själva arrayelementet. Följande kod ökar alltså värdet för varje element i @arr-matrisen med ett:

$i = 19880508 ;
foreach $i (@arr ) (
$i++;
}
# $i är fortfarande 19880508

foreach kan också användas för att arbeta med hash:

%hash = (
aaa => 1 ,
bbb => 2,
) ;
# tangentfunktionen returnerar en array som innehåller alla hash-nycklar
foreach $k (nycklar %hash ) (
skriv ut "$k => $hash($k) \n";
}

I Perl har foreach loop en kort form:

# om du har glömt vad qw-operatorn gör,
# gå tillbaka till den första delen av "Perl Programmering Basics"
för $i (qw/1 2 3/ ) (
skriv ut "$i" ;
}

Det vill säga, praktiskt taget överallt, istället för foreach, kan du helt enkelt skriva för. Perl kommer inte att blanda ihop detta med en real for loop, eftersom den senare kräver semikolon och så vidare.

Medan, tills och gör-loopar fungerar exakt på samma sätt som i C++ eller Pascal/Delphi:

# print "1 2 3 4 5" på fyra olika sätt

$i = 0 ;
medan ($i< 5 ) { # så länge $i är mindre än fem
skriv ut ++ $i . "" ;
}
skriv ut " \n"; # ny linje

$i = 0 ;
tills ($i == 5 ) ( # tills $i är lika med fem
skriv ut ++ $i . "" ;
}
skriv ut " \n";

$i = 0 ;
gör (
skriv ut ++ $i . "" ;
) medan ($i< 5 ) ; # kontrollera i slutet av slingan
skriv ut " \n";

$i = 0 ;
gör (
skriv ut ++ $i . "" ;
) tills ($i == 5 );
skriv ut " \n";

I analogi med if och unless-satserna finns det en förkortad form av skrivslingor:

$i = 0 ;
skriv ut ++ $i . " " medan ($i< 5 ) ;
skriv ut " \n";

$i = 0 ;
skriv ut ++ $i . " " tills ($i == 5 ) ;
skriv ut " \n";

skriv ut "$_" för (qw/1 2 3 4 5/ ); # du kan också foreach(qw/1 2 3 4 5/);
skriv ut " \n";

Lägg märke till den sista framslingan. Vi kommer ihåg att detta är en stenografi för foreach, inte en for loop, eller hur? Den sistnämnda har för övrigt ingen kort ingång. Så namnet på variabeln med vilken vi kommer att komma åt arrayelementen specificerades inte här. Det kan inte användas i förkortningen. I det här fallet används en speciell variabel - $_. Följande exempel fungerar också ganska bra:

för (qw/1 2 3 4/ ) (
skriv ut "$_" ;
}

Den kan förresten skrivas om enligt följande.

6.5.1. Enkla operatörer

Enkel operatör i PERL är detta ett uttryck som kan ha en enda modifierare. Varje enkel sats måste föregås av semikolon om det inte är den sista satsen i ett block; i detta fall kan semikolon utelämnas. Det finns fem enkla operatörsmodifierare:

$count = 5; skriv ut "$count\n" om $count; skriv ut "$count\n" medan $count--; @people = qw/Anna Boris Victor/; skriv ut "$_\n" för varje @people;

Vi kan tillämpa modifierare inte bara på enkla påståenden, utan också på block. För att göra detta måste du sätta ett nyckelord före blocket do:

Gör ( $line = ; ... ) tills $line eq ".\n";

Ett sådant block exekveras alltid minst en gång innan villkoret kontrolleras. Observera att loopkontrollsatser inte fungerar i sådana konstruktioner eftersom modifierare inte har etiketter.

Design do BLOCKERA(utan modifierare) används också i PERL: det låter dig förvandla ett block till ett uttryck och returnerar värdet av den sista satsen i det blocket.

6.5.2. Sammansatta operatörer

Sammansatta operatörer Bestå av block, innesluten i lockiga hängslen. Kom ihåg att, till skillnad från i C eller Java, krävs lockiga klammerparenteser i sammansatta satser, även om de bara omsluter en sats. PERL innehåller följande sammansatta uttalanden:

6.5.2.1. Villkorligt om uttalande

Villkorlig operatör om låter dig kontrollera ett visst tillstånd och, beroende på dess sanning, exekvera en viss sekvens av operatörer. Den har följande former:

om (uttryck) BLOCK1 om (uttryck) BLOCK1 annan BLOCK2 om (uttryck1) BLOCK1 elsif (uttryck2) BLOCK2 ... annan BLOCKn

uttryck sant, sedan sant BLOCK1; om det är falskt överförs kontrollen till den efterföljande operatören om.

uttryck sant, sedan sant BLOCK1; om det är falskt körs det BLOCK2.

Den tredje formen av operatören innebär att om uttryck sant, sedan sant BLOCK1; om det är falskt och sant uttryck2, då är det uppfyllt BLOCK2 etc. Om uttrycken i alla grenar av operatorn är falska, då BLOCKn.

Följande exempel tilldelar variabeln $m till den största av de tre talen $x , $y , $z :

Om ($x >= $y) ( $m = ($x >= $z) ? $x: $z; ) annars ( $m = ($y >= $z) ? $y: $z; )

6.5.2.2. Villkorligt uttalande om inte

Villkorlig operatör såvida inte om. Den har två former:

såvida inte (uttryck) BLOCK1 såvida inte (uttryck) BLOCK1 annan BLOCK2

Den första formen av operatorn betyder att om uttryck falsk, sedan avrättad BLOCK1; om det är sant, överförs kontrollen till den efterföljande operatören såvida inte.

Den andra formen av operatören innebär att om uttryck falsk, sedan avrättad BLOCK1; om det är sant, avrättas sedan BLOCK2.

Det föregående exemplet kan skrivas om enligt följande:

Om inte ($x< $y) { $m = ($x >= $z) ? $x: $z; ) annat ( $m = ($y >= $z) ? $y: $z; )

6.5.2.3. Medan loop operatör

Slingoperatör medan har två former:

medan (uttryck) BLOCKERA medan (uttryck) BLOCKERA Fortsätta BLOCK1

Operatör medan

  1. Värdet beräknas uttryck
  2. Genomförde BLOCKERA.
  3. Fortsätta, då är det uppfyllt BLOCK1.

$i = 0; medan ($i++< 10) { print "$i\n" }

Använder den andra formen av operatören medan, det kan skrivas så här:

$i = 1; medan ($i<= 10) { print "$i\n" } continue { $i++ }

När du använder denna operatör måste du se till att förr eller senare uttryck kommer att bli falsk, för annars kommer programmet att gå in i en oändlig loop, till exempel:

Medan (1) (skriv ut "Hej alla!" )

6.5.2.4. Tills loop-operatör

Slingoperatör fram tills logiskt motsatsen till operatören medan och har även två former:

fram tills (uttryck) BLOCKERA fram tills (uttryck) BLOCKERA Fortsätta BLOCK1

Operatör fram tills görs enligt följande:

  1. Värdet beräknas uttryck. Om det är sant, överförs kontrollen till påståendet efter detta påstående.
  2. Genomförde BLOCKERA.
  3. Om påståendet innehåller ett nyckelord Fortsätta, då är det uppfyllt BLOCK1.
  4. Kontrollen överförs till steg 1.

Följande exempel visar siffrorna ett till tio:

$i = 1; tills ($i > 10) ( skriv ut "$i\n") fortsätt ( $i++ )

6.5.2.5. For loop-operatören

Slingoperatör för har formen:

för (initiering; skick; förändra) BLOCKERA

Operatör för görs enligt följande:

  1. Uttalandet verkställs initiering(vanligtvis initierar den loopräknaren eller räknarna).
  2. Värdet på uttrycket beräknas skick. Om det är falskt överförs kontrollen till den operatör som följer denna operatör.
  3. Genomförde BLOCKERA.
  4. Uttalandet verkställs förändra(vanligtvis ökar eller minskar den loopräknaren eller räknarna) och kontrollen överförs till steg 2.

Denna operatör används vanligtvis i de fall då antalet repetitioner av slingan är känt i förväg. Så vi skulle kunna skriva det föregående exemplet kortare:

För ($i = 1; $i<= 10; $i++) { print "$i\n" }

6.5.2.6. Iterationsoperator foreach

Operatör för varje utför specificerade åtgärder för varje element i en lista eller array. Den har två former:

för varje variabel (lista) BLOCKERA för varje variabel (lista) BLOCKERA Fortsätta BLOCK1

Operatör för varje görs enligt följande:

  1. Variabel tilldelas nästa element lista. Om listan är uttömd, överförs kontrollen till operatören efter den angivna.
  2. Genomförde BLOCKERA.
  3. Om påståendet innehåller ett nyckelord Fortsätta, då är det uppfyllt BLOCK1.
  4. Kontrollen överförs till steg 1.

Låt oss ge samma exempel med att skriva ut nummer från 1 till 10:

Foreach $i (1..10) ( skriv ut "$i\n" )

Variabelär lokal för en given operatör, d.v.s. efter avslutad iteration återställs dess tidigare värde. Om du sätter nyckelordet före en variabel min, då kommer det att vara lexikalt begränsat till operatörens kropp. Om variabel utelämnas, används specialvariabeln $_:

Foreach (1..10) ( skriv ut "$_\n")

Om ett av elementen listaär en array, bör slingans kropp inte ändra den, annars blir resultaten oförutsägbara.

Faktum är att operatörerna för Och för varjeär synonymer och du kan använda vilket som helst av dessa ord som du vill.

6.5.2.7. Operatörsetiketter

Till operatörerna medan, fram tills, för Och för varje, och kan även placeras framför block taggar. Den markerade operatören har formen:

märka: operatör

Etiketten kan vara vilken identifierare som helst som inte är ett reserverat ord, men i PERL är det vanligt att skriva etiketter med versaler.

Även om användningen av etiketter i modern programmering anses vara dålig, förenklar deras användning i vissa fall avsevärt programmets logik. Detta inträffar oftast när etiketter används för att överföra kontroll från en djupt kapslad slinga till en yttre slinga. Tänk på följande exempel, skrivet i de bästa traditionerna av C++:

För (min $i = 0; $i< @ary1; $i++) { for (my $j = 0; $j < @ary2; $j++) { if ($ary1[$i] >$ary2[$j]) ( sista; ) $ary1[$i] += $ary2[$j]; ))

Etiketter och slingstyrningsoperatorer låter dig skriva den här algoritmen mycket kortare och, viktigast av allt, mycket mer transparent:

YTTRE: för min $x (@ary1) ( för min $y (@ary2) ( nästa YTTRE om $x > $y; $x += $y; ) )

6.5.2.8. sista operatören

Operatör sista avslutar omedelbart den angivna slingan. Den har två former:

sista märka sista

Den första formen av operatören avslutar slingan med det givna märka. Det andra formuläret slutför exekveringen av den innersta kapslade slingan som körs för närvarande. Om slingan har ett block Fortsätta, då körs den inte. Exempel:

LINE: medan ( ) ( sista raden om /^$/; # bryter slingan om en tom rad påträffas... )

6.5.2.9. nästa operatör

Operatör Nästa börjar en ny iteration av den angivna slingan. Den har två former:

Nästa märka Nästa

märka Fortsätta, så kommer den att köras innan en ny iteration påbörjas. Exempel:

LINE: medan ( ) (nästa RAD om /^#/; # hoppa över kommentarer...)

6.5.2.10. göra om operatör

Operatör göra om börjar en ny iteration av den angivna slingan utan att kontrollera villkoret för dess exekvering. Den har två former:

göra om märka göra om

Den första formen av operatören börjar en ny iteration av slingan med det givna märka. Den andra formen börjar en ny iteration av den innersta kapslade slingan som körs för närvarande. Om slingan har ett block Fortsätta, då körs den inte. Följande exempel tar bort kommentarer från ett Pascal-program där de har formen () (exemplet är förenklat eftersom det inte tar hänsyn till att ()-tecken kan finnas i strängkonstanter):

LINE: medan ( ) ( medan (s|((.*).*)(.*)|$1 |) () s|(.*)| |; if (s|(.*| |) ( $front = $_; medan ( ) ( om (/)/) ( s|^|$front\(|; gör om LINE; ) ) ) skriv ut; )

6.5.2.11. Block som en degenererad cykel

Ett block behandlas i PERL som en loop, villkorslöst exekverat en gång. Det gör att vi kan använda konstruktionen

BLOCK1 Fortsätta BLOCK2

vilket vanligtvis betyder att den är igång BLOCK1, och efter det BLOCK2. Men att behandla block som loopar innebär också att vi kan använda loop control-satser inuti blocken, i vilket fall denna konstruktion blir mycket användbar.

En av anledningarna till att PERL inte inkluderar en select-sats växla, är att det är väldigt enkelt att modellera med block och loopkontrollsatser, till exempel:

SWITCH: ( $abc = 1, sista SWITCH om /^abc/; $def = 1, sista SWITCH om /^def/; $xyz = 1, sista SWITCH om /^xyz/; $ingenting = 1; )

6.5.2.12. gå till operatör

PERL innehåller en hoppoperator gå till tre typer:

gå till märka gå till uttryck gå till &namn

Den första formen av operatören överför kontrollen till operatören med det angivna märka. Kontroll kan inte överföras inuti en struktur som kräver initiering, till exempel inuti en subrutin eller uttalande för varje.

Den andra formen är "beräknbar" gå till": den beräknar värdet uttryck och överför kontrollen till den resulterande etiketten, till exempel:

Goto("LABEL1", "LABEL2", "LABEL3")[$i];

Den tredje formen är inte alls gå till i ordets vanliga bemärkelse. Denna operatör ersätter ett subrutinsamtal namn istället för den subrutinen som körs för närvarande. Den används av AUTOLOAD()-rutiner som tyst vill ersätta anropet från en rutin med en annan. namn behöver inte vara namnet på en subrutin; det kan vara en skalär variabel eller ett block vars värde är en referens till en subrutin.

Förutom den omfattande listan över strängjämförelseoperatörer, lägger Sinan Ünür Perl 5.10 till en smart matchningsoperatör.

Den smarta matchningsoperatören jämför två element baserat på deras typ. Se diagram nedan för 5.10-beteende (jag tror att detta beteende ändras något i 5.10.1):

perldoc perlsyn "Smart matchning i detalj":

Beteendet för smart matchning beror på vad argumenten är. Den är alltid kommutativ, d.v.s. $a ~~ $b beter sig på samma sätt som $b ~~ $a . Beteendet bestäms av följande tabell: Den första raden, som tillämpas i valfri ordning, avgör matchningens beteende.

$a $b Typ av matchning Implicit matchningskod ====== ===== ======= ======== ===== (överbelastning övertrumfar allt) Kod[+] Kod[+] referenslikhet $a == $b Valfri kod[+] skalär subsanning $b−>($a) Hash Hash hash nycklar identiska ~~ Hash Array hash segment existens grep (finns $a−>($_ )) @$b Hash Regex hash-nyckel grep grep /$b/, nycklar %$a Hash Alla hash-poster existerar $a−>($b) Array Array arrays är identiska[*] Array Regex array grep grep /$b /, @$a Array Num array innehåller nummer grep $_ == $b, @$a Array Vilken array som helst innehåller sträng grep $_ eq $b, @$a Alla undef undefined !defined $a Alla regexmönster matchar $a = ~ /$b/ Code() Code()-resultat är lika med $a−>() eq $b−>() Vilken kod() enkel stängning sanning $b −>() # ignorerar $a Num numish[!] numerisk likhet $a == $b Valfri Str-stränglikhet $a ekv $b Vilken som helst Num numerisk likhet $a == $b Vilken som helst Valfri stränglikhet $a ekv $b + − detta måste vara en kodreferens vars prototyp (om sådan finns) är inte "" (subs med en ""-prototyp hanteras av "Code()"-posten längre ner) * − det vill säga varje element matchar elementet i samma index i den andra arrayen. Om en cirkulär referens hittas faller vi tillbaka till referenslikhet. ! − antingen ett reellt tal eller en sträng som ser ut som ett tal

Naturligtvis är en "matchningskod" inte en faktisk matchningskod: den förklarar helt enkelt den avsedda innebörden. Till skillnad från grep kommer smart match-operatorn att loopa när det är möjligt.

Anpassad mappning via överbelastning Du kan ändra hur ett objekt mappas genom att överbelasta ~~-operatorn. Detta är överlägset konventionell smart matchningssemantik. Se överbelastning.

För att jämföra skalära data eller värdena på skalära variabler tillhandahåller Perl en uppsättning binära operatorer som utvärderar likhet, större än, större än eller lika med etc. relationer mellan deras operander, varför denna grupp av operatorer också kallas relationsoperatörer. Perl använder olika operationer för att jämföra numeriska data och strängdata. Alla presenteras i tabell. 4.1.

Tabell 4.1. Relationsverksamhet

Drift Numerisk Sträng Menande
Jämlikhet == ekv Sant om operanderna är lika, annars falskt
Olikhet != ne Sant om operanderna inte är lika, annars falskt
Mindre < lt Sant om den vänstra operanden är mindre än den högra operanden, annars falskt
Mer > GT Sant om den vänstra operanden är större än den högra operanden, annars falskt
Mindre eller lika <= le Sant om den vänstra operanden är större än eller lika med den högra operanden, annars falskt
Mer eller lika >= ge Sant om den högra operanden är större än eller lika med den vänstra operanden, annars falskt
Jämförelse <=> cmt 0 om operanderna är lika
1 om den vänstra operanden är större än den högra operanden
-1 om den högra operanden är större än den vänstra

Resultatet av relationsoperationer (förutom den sista jämförelsen) är True, värdet 1, eller False, den tomma strängen "".

Kommentar
Värdet sant i aritmetiska operationer tolkas som siffran 1 och i strängoperationer som strängen "1". Värdet false i aritmetiska operationer tolkas som talet 0 och i strängoperationer som den tomma strängen " ".

Numeriska relationsoperationer

Numeriska relationsoperationer tillämpas på numeriska data, där en eller båda operanderna kan specificeras av en sträng som innehåller ett giltigt decimaltal. I numeriska relationsoperationer, om någon operand specificeras av en sträng vars innehåll inte representerar ett giltigt decimaltal, sätts dess värde till o och en varning visas som indikerar att operanden inte används korrekt i den numeriska relationsoperationen (om Perls varningsläge är aktiverat). Betydelsen av relationsoperationer för numeriska data motsvarar de vanliga matematiska operationerna för att jämföra tal (exempel 4.7).

123 > 89; # Resultat: 1 (sant)

123 < 89; # Результат: "" (ложь)

123 <= 89; # Результат: "" (ложь)

89 <= 89; # Результат: 1 (истина)

23 >= 89; # Resultat: "" (false)

23 <=>89; # Resultat: -1 (höger operand är större än vänster operand)

89 <=>23; # Resultat: 1 (höger operand är större än vänster operand)

Användningen av numeriska jämförelseoperationer är inte svårt, men när man jämför för lika decimaltal med flyttal, kan avrundningseffekter uppträda på grund av det begränsade antalet signifikanta siffror i mantissan för representationen av reella tal i en dator och leder till " felaktig” användning av jämförelseoperationer ur användarens synvinkel . Exempel 4.8 illustrerar en liknande situation.

#! peri -w
$z = 0,7;

$zz = 10+0,7-10; # Variabeln $zz innehåller talet 0,7

# Skriv ut strängen "z är lika med zz" om värdena för variablerna $z och $zz är lika skriv ut "z lika med zz\n" om ($z == $zz);

När vi försöker köra exempel 4.8 blir vi förvånade över att vårt program inte kommer att skriva ut någonting. Vad är problemet? Lösningen ligger i operatorn för att beräkna värdet på variabeln $zz. När du utför aritmetiska operationer resulterar avrundningsfel i ett värde på 0,6999999999999999 (du kan infoga variabeln $zz print-satsen och verifiera detta), även om det är nära 0,7, är det inte exakt lika med det. Därför fungerade jämförelseoperationen korrekt!

Råd
Använd inte jämförelseoperatorn för likhet mellan reella tal, dess resultat kanske inte motsvarar vad som förväntas ur en matematisk synvinkel. Om du behöver kontrollera likheten mellan två reella tal, är det bättre att jämföra det absoluta värdet av deras skillnad med ett mycket litet tal (beroende på vilken precision som krävs):

abs($a-$b)<= 0.00000001; # Проверка равенства

Sträng relationsoperationer

Jämförelse av strängdata baseras på deras ordning enligt ASCII-kodtabellen, dvs tecknet med den lägre ASCII-koden föregår tecknet med den högre ASCII-koden. Strängjämförelser utförs tecken för tecken från vänster till höger. Detta betyder att om de första tecknen på raderna är lika, så jämförs de andra, och om de är lika, så jämförs de tredje, etc. Dessutom, om raderna är av olika längd, då antalet tecken med kod o som saknas för likhet läggs till i slutet av raden med kortare längd. Det bör noteras att, till skillnad från vissa andra programmeringsspråk, i Perl är de efterföljande blankstegstecken betydande när man jämför strängar. Exempel 4.9 visar strängjämförelser som illustrerar reglerna som beskrivs.

"A" Det "a"; # Resultat: sant (kod "A" är \101, kod "a" är \141)
"a" Det "aa";
# med koden \000, vilket är mindre än koden \141
# andra tecken "a" i strängen i den högra operanden)
"a" Det "a"; # Resultat: sant (tecknet läggs till i strängen "a"
# med koden \000, vilket är mindre än koden \040
# efterföljande mellanslag för den högra operandsträngen)
"12" Det "9"; # Resultat: sant (kod "1" - \061, kod "9" - \071)
"9" ekv 09"; # Resultat: false (kod " " - \040, kod "O" - \060)

Låt oss vara uppmärksamma på de två sista jämförelseoperationerna för strängliteraler. Innehållet i deras operander kan omvandlas till korrekta tal, och därför gäller liknande numeriska relationsoperationer för dem. Däremot kommer deras resultat att skilja sig betydligt från resultatet av att utföra strängrelationsoperationer. När du använder operationen< в предпоследнем выражении результат будет Ложь, а если в последнем выражении применить операцию ==, то результат будет Истина. Об этом всегда следует помнить, так как Perl автоматически преобразует символьные данные в числовые там, где это необходимо.