perlop - Operatori Perl e precedenze
La precedenza e l'associatività degli operatori in Perl funzionano
grossomodo come funzionano in matematica.
Precedenza degli operatori significa che alcuni operatori vengono
valutati prima di altri. Ad esempio, in 2 + 4 * 5, la moltiplicazione
ha una precedenza maggiore, così 4 * 5 viene valutato per
primo, risultando in 2 + 20 == 22 e non 6 * 5 == 30.
Associatività degli operatori > definisce cosa accade quando
uno stesso operatore viene utilizzato più volte: ossia, se
viene valutata prima l'operazione a sinistra o prima quella a destra.
Ad esempio, in 8 - 4 - 2, la sottrazione è associativa a
sinistra, così Perl valuta l'espressione da sinistra a destra.
8 - 4 viene valutato prima, rendendo l'operazione 4 - 2 == 2
e non 8 - 2 == 6.
Gli operatori Perl hanno le seguenti associatività e precedenze,
elencate dalla precedenza più alta a quella più bassa.
Operatori presi in prestito dal C mantengono fra di loro la stessa relazione di
precedenza, anche nei casi in cui la precedenza del C
è leggermente inappropriata (questo rende più
facile imparare il Perl ai programmatori C). Con rarissime eccezioni,
tutti questi operatori operano soltanto su valori scalari, non su array.
sinistra termini e operatori su liste (ass. sinistra)
sinistra ->
nonassoc ++ --
destra **
destra ! ~ \ e + e - unari
sinistra =~ !~
sinistra * / % x
sinistra + - .
sinistra << >>
nonassoc operatori unari con nome
nonassoc < > <= >= lt gt le ge
nonassoc == != <=> eq ne cmp
sinistra &
sinistra | ^
sinistra &&
sinistra ||
nonassoc .. ...
destra ?:
destra = += -= *= ecc.
sinistra , =>
nonassoc operatori su liste (ass. destra)
destra not
sinistra and
sinistra or xor
Nelle sezioni seguenti, questi operatori sono documentati in ordine di
precedenza.
Molti operatori possono essere sottoposti ad overload per oggetti. Vedere
overload.
Un TERMINE ha in Perl la precedenza più alta. Sono termini le variabili,
le virgolette e gli operatori che si comportano come virgolette, qualunque espressione fra parentesi
e ogni funzione i cui argomenti sono racchiusi fra parentesi. In realtà
non esistono propriamente funzioni in tal senso, ma operatori di lista e operatori
unari che si comportano come funzioni quando vengono messe le parentesi attorno
agli argomenti. Questi operatori sono tutti documentati in perlfunc.
Se un qualunque operatore di lista (print(), ecc.) o un qualunque
operatore unario (chdir(), ecc.) è seguito seguito da una
parentesi aperta come token successivo, l'operatore e gli argomenti fra
le parentesi vengono valutati con la precedenza più alta, come
una normale chiamata di funzione.
In assenza di parentesi, la precedenza degli operatori di lista come
print, sort, o chmod è molto alta o molto bassa a
seconda che si consideri ciò che si trova a sinistra o a
destra dell'operatore. Ad esempio, in
@ary = (1, 3, sort 4, 2);
print @ary; # stampa 1324
le virgole a destra di sort vengono valutate prima dell'ordinamento,
ma le virgole a sinistra vengono valutate dopo. In altri termini, gli
operatori di lista tendono a mangiarsi tutti gli argomenti che li
seguono, e si comportano dunque come un semplice termine nei confronti
dell'espressione che li precede.
Occorre fare attenzione con le parentesi:
# Queste righe valutano exit prima di print:
print($foo, exit); # Decisamente non quello che si vuole.
print $foo, exit; # Neanche questo.
# Queste eseguono print prima di valutare exit:
(print $foo), exit; # Questo va bene.
print($foo), exit; # Oppure questo.
print ($foo), exit; # anche questo.
Si noti anche che
print ($foo & 255) + 1, "\n";
probabilmente non fa ciò che di primo acchitto ci si
aspetterebbe. Le parentesi racchiudono la lista di argomenti per
print, che viene valutato (e stampa il risultato di $foo &
255). Poi viene aggiunto uno al valore restituito da print
(solitamente 1). Il risultato è una cosa simile a:
1 + 1, "\n"; # Ovviamente non quello che si intendeva.
Per ottenere il risultato corretto bisogna scrivere:
print(($foo & 255) + 1, "\n");
Si veda anche Operatori unari con nome per un ulteriore approfondimento.
Vengono interpretati come termini anche i costrutti do {} e eval
{}, le chiamate a subroutine e metodi, e i costruttori anonimi []
e {}.
Vedere anche Virgolette e operatori simili verso la fine di questa sezione, e Operatori di I/O.
>>
``->'' è un operatore infisso di dereferenziazione, come in C e
C++. Se sul lato destro si trova un qualcosa come [...], {...}, o
(...), allora il lato sinistro deve essere un riferimento concreto o
simbolico a, rispettivamente, un array, un hash, o una subroutine (o,
tecnicamente parlando, una locazione in grado di contenere un riferimento
concreto, se si tratta di un riferimento ad array o hash utilizzato in un
assegnamento). Vedere perlreftut e perlref.
Altrimenti, il lato destro è il nome di un metodo, o una
variabile scalare semplice contenente o il nome del metodo o un
riferimento a subroutine, e il lato sinistro deve essere un oggetto
(un riferimento cui è stato applicato bless) oppure un nome
di classe (ossia il nome di un package). Vedere in questo caso
perlobj.
``++'' e ``--'' funzionano come in C. Ossia, se posti prima di una variabile,
incrementano o decrementano la variabile di uno prima di restituirne
il valore, mentre se posti dopo, la incrementano o decrementano dopo averne restituito il valore.
$i = 0; $j = 0;
print $i++; # stampa 0
print ++$j; # stampa 1
L'operatore di auto-incremento ha un po' di magia in più. Se viene
incrementata una variabile numerica, o che è stata usata in contesto
numerico, si ottiene un incremento normale. Se, invece, la variabile è
stata utilizzata solo in contesto stringa dalla sua impostazione, e contiene
un valore che non è la stringa vuota e soddisfa l'espressione
/^[a-zA-Z]*[0-9]*\z/, allora l'incremento viene fatto sulla stringa,
conservando ciascun carattere nel suo proprio intervallo, con eventuale riporto al
carattere successivo:
print ++($foo = '99'); # stampa '100'
print ++($foo = 'a0'); # stampa 'a1'
print ++($foo = 'Az'); # stampa 'Ba'
print ++($foo = 'zz'); # stampa 'aaa'
undef viene sempre trattato come numerico, e in particolare viene modificato
in 0 prima dell'incremento (in modo che un post-incremento di un valore
indefinito restituisca 0 invece di undef).
L'operatore di auto-decremento non è magico.
L'operatore binario ``**'' è l'operatore di elevazione a
potenza. Ha una associatività maggiore persino del meno
unario, quindi -2**4 vuoldire -(2**4), non (-2)**4. È
implementato utilizzando la funzione C pow(3), che internamente
utilizza dei double (numeri in virgola mobile).
Il ``!'' unario effettua una negazione logica, ossia ``non''. Vedere
anche not per una versione dello stesso operatore con precedenza
più bassa.
Il ``-'' unario effettua una negazione aritmetica se l'operando
è numerico. Se l'operando è un identificatore, viene
restituita una stringa consistente nel segno meno seugito
dall'identificatore. Altrimenti, se la stringa inizia con un
piè o un meno, viene restituita una stringa che inizia con il
segno opposto. Un effetto di tali regole è che -pippo
è equivalente a "-pippo". Se, però, la stringa
comincia con con carattere non alfabetico (a parte + o -), Perl
proverà a convertirla in un numero e effettuare la negazione
aritmetica. Se la stringa non può essere convertita
correttamente in un numero, Perl emetterà l'avviso Argument
``the string'' isn't numeric in negation (-) at ... (``L'argomento non
è numerico durante una negazione (-) alla riga...'').
Il ``~'' unario effettua una negazione bit a bit, ossia il
complemento ad 1. Ad esempio, 0666 & ~027 è uguale a 0640
(vedere anche Aritmetica Intera e Operatori di bit su stringhe). Da notare che la dimensione in bit dei valori restituiti
dipende dalla piattaforma: ~0 è lungo 32 bit su piattaforme
a 32 bit, ma 64 bit su piattaforme a 64 bit; quindi, se ci si aspetta
un certo numero di bit, si ricordi di utilizzare l'operatore & per
rimuovere i bit in eccesso.
Il ``+'' unario non ha alcun effetto, neanche sulle stringhe. Ha una
utilità sintattica per separare un nome di funzione da
un'espressione in parentesi che sarebbe altrimenti interpretata come
lista dei parametri della funzione (vedere gli esempi sopra alla voce
Termini e operatori di lista (associatività a sinistra)).
Il ``\'' unario crea un riferimento a qualunque cosa segua. Vedere
perlreftut e perlref. Quest'operazione non è da
confondere con l'utilizzo della backslash all'interno di stringhe, per
quanto entrambe le forme implichino la nozione di proteggere
ciò che segue dall'interpolazione del loro valore.
Il ``=~'' binario effettua un pattern match su un'espressione scalare. Alcune operazioni agiscono su, o modificano, la stringa contenuta in $_ per default. Tramite questo operatore è possibile compiere l'operazione su un'altra stringa. L'argomento di destra è un pattern di ricerca, sostituzione o traslitterazione. L'argomento di sinistra è ciò su cui si intende effettuare la ricerca, sostituzione o traslitterazione invece del default $_. Quando utilizzato in contesto scalare, il valore restituito indica generalmente il successo dell'operazione. Il comportamento in contesto lista dipende dalla singola operazione. Vedere Regexp Quote-Like Operators per i dettagli.
Se l'argomento di destra è un'espressione invece di un pattern di ricerca, sostituzione o traslitterazione, viene interpretato come pattern di ricerca a runtime.
Il ``!~'' è come ``=~'', solo che il valore restituito viene logicamente negato.
Il ``*'' binario moltiplica due numeri.
Il ``/'' binario divide due numeri.
Il ``%'' binario calcola il modulo di due numeri. Dati gli operandi interi $a e $b: se $b è positivo, $a % $b è $a meno il multiplo maggiore di $b che non è superiore ad $a. Se $b è negativo, $a % $b è $a meno il multiplo minore di $b che non è minore di $a (ossia il risultato sarà minore o uguale a zero).
Si noti che se si sta utilizzando il pragma integer, l'operatore ``%'' utilizza direttamente il corrispondente operatore C, come implementato dal vostro compilatore. Questo significa che il risultato con operandi negativi non è ben definito, ma l'esecuzione sarà più veloce.
Il ``x'' binario è l'operatore di ripetizione. In contesto scalare, o se l'operando di sinistra non è posto fra parentesi, restituisce una stringa composta dell'operando di sinistra ripetuto il numero di volte specificato dall'operando di destra. In contesto lista, se l'operando di sinistra è posto fra parentesi, ripete la lista.
print '-' x 80; # stampa una riga di trattini
print "\t" x ($tab/8), ' ' x ($tab%8); # [?tab over]
@uni = (1) x 80; # una lista di 80 uni
@uni = (5) x @uni; # imposta tutti gli elementi a 5
Il ``+'' binario restituisce la somma di due numeri.
Il ``-'' binario restituisce la differenza di due numeri.
Il ``.'' binario concatena due stringhe.
Il ``<<'' binario restituisce il valore dell'operando di sinistra ruotato a sinistra del numero di bit specificato dall'operando di destra. Gli operandi dovrebbero essere interi (vedere anche Integer Arithmetic).
Il ``>>'' binario restituisce il valore dell'operando di sinistra ruotato a destra del numero di bit specificato dall'operando di destra. Gli operandi dovrebbero essere interi (vedere anche Integer Arithmetic).
Si noti che sia ``<<'' che ``>>'' sono implementati in Perl utilizzando
direttamente i corrispondenti operatori C. Se si sta utilizzando use
integer (vedere Integer Arithmetic) vengono utilizzati dei signed integer
del C, altrimenti vengono utilizzati unsigned integer. In entrambi i casi, l'implementazione non genererà risultati che siano maggiori della dimensione degli integer con i quali il Perl è stato compilato (32 o 64 bit).
Il risultato di oltrepassare il limite consentito per gli integer non è definito, poiché non è definito neanche in C. In altre parole, usando integer a 32 bit, il risultato di 1 << 32 è indefinito. Anche lo shift di un numero negativo di bit è indefinito.
I vari operatori unari con nome sono trattati come funzioni con un argomento, con parentesi opzionali.
Se qualsiasi operatore list (print(), ecc.) o qualunque operatore unario
(chdir(), ecc.) e' seguito da una parentesi come token successivo, l'operatore
e gli argomenti dentro le parentesi sono interpretati come a precedenza
maggiore, proprio come normali chiamate di funzione. Per esempio, dato che gli
operatori unari con nome hanno precedenza maggiore di ||:
chdir $foo || die; # (chdir $foo) || die
chdir($foo) || die; # (chdir $foo) || die
chdir ($foo) || die; # (chdir $foo) || die
chdir +($foo) || die; # (chdir $foo) || die
ma, dato che * ha precedenza maggiore rispetto agli operatori con nome:
chdir $foo * 20; # chdir ($foo * 20)
chdir($foo) * 20; # (chdir $foo) * 20
chdir ($foo) * 20; # (chdir $foo) * 20
chdir +($foo) * 20; # chdir ($foo * 20)
rand 10 * 20; # rand (10 * 20)
rand(10) * 20; # (rand 10) * 20
rand (10) * 20; # (rand 10) * 20
rand +(10) * 20; # rand (10 * 20)
Per quanto riguarda la precedenza, gli operatori di test sui file, come -f, -M, ecc. sono trattati come gli operatori unari con nome, ma non seguono le regole di funzionamento delle parentesi. Ciò significa, per esempio, che -f($file).``.bak''> è equivalente a -f "$file.bak".
Si veda anche Termini e Operatori Lista (Leftward).
=head2 Operatori di confronto
L'operatore binario ``<'' restituisce un valore vero se l'argomento a sinistra è numericamente minore dell'argomento a destra.
>
L'operatore binario ``>'' restituisce un valore vero se l'argomento a sinistra è numericamente maggiore dell'argomento a destra.
>>
L'operatore binario ``<='' restituisce un valore vero se l'argomento a sinistra
è numericamente minore o uguale dell'argomento a destra
>
L'operatore binario ``>='' restituisce un valore vero se l'argomento a sinistra
è numericamente maggiore o uguale dell'argomento a destra.
= >>
L'operatore binario ``lt'' restituisce un valore vero se l'argomento a sinistra, visto come stringa, è minore dell'argomento a destra.
>
L'operatore binario ``gt'' restituisce un valore vero se l'argomento a sinistra, visto come stringa, è maggiore dell'argomento a destra.
>
L'operatore binario ``le'' restituisce un valore vero se l'argomento a sinistra, visto come stringa, è minore o uguale dell'argomento a destra.
>
L'operatore binario ``ge'' restituisce un valore vero se l'argomento a sinistra, visto come stringa, è maggiore o uguale dell'argomento a destra.
>
L'operatore binario ``=='' restituisce un valore vero se l'argomento a sinistra
è numericamente uguale all'argomento a destra.
L'operatore ``!='' restituisce un valore vero se l'argomento a sinistra
è numericamente non uguale all'argomento a destra.
L'operatore ``<=>'' restituisce -1, 0, o 1 a seconda che l'argomento a sinistra
sia numericamente minore, uguale, o maggiore dell'argomento a destra. Se la
vostra piattaforma supporta NaNs (not-a-numers) come valori numerici, usando
questi con ``<=>'' restituisce undef. NaN non è ``<'', ``=='', ``>'', ``<='' o
``>='' a qualsiasi cosa (anche NaN), quindi questi 5 restituiscono false. NaN != NaN restituisce un valore vero, così NaN != qualsiasi altra cosa. Se la vostra piattaforma non supporta NaN allora NaN è solamente una
stringa con valore numerico uguale a 0.
>>
perl -le '$a = "NaN"; print "NaN non supportato qui" if $a == $a'
perl -le '$a = "NaN"; print "NaN supportato" if $a != $a'
L'operatore binario ``eq'' restituisce un valore vero se l'argomento a sinistra, visto come stringa, è uguale all'argomento a destra.
L'operatore binario ``ne'' restituisce un valore vero se l'argomento a sinistra, visto come stringa, non è uguale all'argomento di destra.
L'operatore binario ``cmp'' restituisce -1, 0 o 1 a seconda che l'argomento a
sinistra sia, visto come stringa, minore, uguale o maggiore dell'argomento a
destra.
``lt'', ``le'', ``ge'', ``gt'' e ``cmp'' usano l'ordinamento specificato dal locale
corrente se use locale è abilitato. Si veda anche perllocale.
L'operatore binario ``&'' restituisce l'AND bit a bit dei suoi operandi.
(Si veda anche Aritmetica Intera e Operatori bit a bit sulle stringhe.)
Notate che ``&'' ha priorità minore degli operatori di confronto, per esempio le parentesi sono essenziali in un test come
print "Anche\n" if ($x & 1) == 0;
L'operatore binario ``|'' restituisce l'OR bit a bit dei suoi operandi.
(Si veda anche Aritmetica Intera e Operatori bit a bit sulle stringhe.)
L'operatore binario ``^'' restituisce lo XOR bit a bit dei suoi operandi.
(Si veda anche Aritmetica Intera e Operatori bit a bit sulle stringhe.)
Notate che gli operatori ``|'' e ``^'' hanno priorità minore rispetto agli operatori di confronto, ad esempio le parentesi sono essenziali in un
confronto come
print "falso\n" if (8 | 2) != 10;
L'operatore binario ``&&'' esegue l'operazione di AND logico cortocircuitato.
Ciò vuol dire che, se l'operando a sinistra è falso, l'operando a destra non verrà valutato. Il contesto scalare o quello lista viene propagato sulla valutazione del secondo operando, se questa avviene.
Esempi by dakkar:
##il primo operando e' vero, il contesto lista e' propagato
##al secondo operando di &&
@a= 1 && ('abc'=~/(.)(.)(.)/)
dopo @a==qw(a b c)
##il primo operando e' vero, il contesto scalare e' propagato
##al secondo operando di &&
$a= 1 && ('abc'=~/(.)(.)(.)/)
dopo, $a==1
##in questo caso il primo operando e' falso (c'e' \d su un carattere)
##quindi torna falso e lista vuota
@a= ('abc'=~/(\d)(\d)(\d)/) && ('abc'=~/(.)(.)(.)/) --> @a=('')
=head2 Or logico in stile C
X<||> X<operator, logical, or>
L'operatore binario ``||'' esegue l'operazione di OR logico cortocircuitato.
Ciò vuol dire che se l'operatore a sinistra e' vero, l'operatore a
destra non sarà valutato. Il contesto scalare o quello lista viene propagato sulla valutazione del secondo operando, se questa avviene.
Gli operatori || e && restituiscono l'ultimo valore valutato
(diversamente dal || e il && del C, il quale restituisce 0 o 1). Quindi, un modo ragionevolmente portabile di scoprire la propria home directory potrebbe essere:
$home = $ENV{'HOME'} || $ENV{'LOGDIR'} ||
getpwuid($<))[7] || die "Sei senza casa!\n";
In particolare, questo significa che non dovreste utilizzare questo metodo
per selezionare tra due aggregati per l'assegnamento:
@a = @b || @c; # questo E<egrave> sbagliato
@a = scalar(@b) || @c; # E<egrave> stato interpretato cosE<igrave>
@a = @b ? @b : @c; # questo funziona bene
Come alternative più leggibili a && e ||, quando usate perl il
controllo del flusso, Perl fornisce gli operatori and e or (si veda sotto). Il comportamento del cortocircuito è identico. La precedenza di ``and'' e ``or'' è molto minore, comunque, in maniera tale che possiate utilizzarli dopo un operatore lista senza il bisogno delle parentesi:
unlink "alpha", "beta", "gamma"
or gripe(), next LINE;
Con gli operatori stile C questo sarebbe stato scritto così:
unlink("alpha", "beta", "gamma")
|| (gripe(), next LINE);
Usare ``or'' per l'assegnamento corrisponde a fare inverosimilmente ciò
che si vuole; si veda sotto.
L'operatore binario ``..'' è l'operatore di rango, che si comporta come
due operatori realmente differenti in base al contesto di utilizzazione. In
contesto lista, esso ritorna una lista di valori contando (uno dopo l'altro)
dal valore di sinistra al valore di destra. Se il valore di sinistra è maggiore di quello di destra allora viene restituita una lista vuota. L'operatore di rango è utile per scrivere foreach (1..10) cicli e per fare operazioni di slice sugli array. Nell'implementazione corrente, non viene
creato un array temporaneo quando l'operatore di rango viene utilizzato come
espressione nei cicli di tipo foreach, ma nelle più vecchie
versioni di Perl potrebbe sprecare molta memoria quando scrivete qualcosa come questo:
for (1 .. 1_000_000) {
# code
}
L'operatore di rango funziona anche sulle stringhe, usando il magico
auto-incremento, si veda sotto.
In contesto scalare, ``..'' restituisce un valore booleano. L'operatore è bi-stabile [ha due stati, NdT] come un flip-flop [dispositivo elettronico di memoria elementare, NdT] ed emula l'operatore virgola di sed, awk, e vari editor. Ciascun operatore ``..'' mantiente il suo personale stato booleano. Esso è falso finchè il suo operando a sinistra è falso. Una volta che l'operando a sinistra diventa vero, l'operatore di rango rimane vero finchè l'operando a destra è vero, DOPODICHÈ l'operatore di rango diventa falso di nuovo. Non diventa falso fino alla prossima volta che l'operatore di rango verrà valutato. Esso può testare l'operando di destra e diventare falso durante la stessa valutazione in cui era diventato vero (come in awk), ma rimarrà ancora una volta vero. Se non volete che testi l'operando a destra fino alla prossima valutazione, come in sed, allora usate tre punti (``...'') invece di due. In altre valutazioni, ``...'' si comporta giusto come ``..'' fa.
L'operando di destra non viene valutato quando l'operatore si trova nello stato di falso, e l'operando di sinistra non viene valutato quando l'operatore si trova invece nello stato di vero. La precedenza è leggermente minore rispetto a quella di || e &&. Il valore restituito può essere sia una stringa vuota per lo stato di falso, oppure una sequenza di numeri (che cominciano con 1) per lo stato di vero. Il numero di sequenza viene resettato per ogni rango incontrato. Il numero di sequenza finale in un rango ha appesa ad esso la stringa ``E0'', la quale non altera il suo valore numerico, ma vi offre un qualcosa di utile per cercarla se volete escludere un estremo. Potete escludere il punto di inizio aspettando che il numero di sequenza sia maggiore di 1.
Se nemmeno l'operando di ``..'' è un'espressione costante, quell'operando è considerato vero se è uguale (==) al numero dell'``input line'' corrente (la variabile $.).
Per esser pignoli, il confronto è realmente int(EXPR) == int(EXPR), ma è solamente un problema se usi un'espressione in virgola mobile; quando implicitamente usate $. come descrito nel precedente paragrafo, il confronto tra int(EXPR) == int($.) diventa un problema quando $. è settato ad un valore in virgola mobile e non state leggendo da un file. Inoltre, "span" .. "spat" oppure 2.18 .. 3.14 non faranno quello che vi aspettate in contesto scalare perchè ciascun operando viene valutato utilizzando la sua rappresentazione intera.
Esempi:
come operatore scalare:
if (101 .. 200) { print; } # stampa le seconde 100 di un file
a
Il ``?:'' ternario è l'operatore condizionale, proprio come in C. Funziona grossomodo come un if-then-else (se-allora-altrimenti). Se l'argomento prima del ? è vero, restituisce l'argomento prima del :, altrimenti restituisce l'argomento dopo il :. Ad esempio:
printf "Io ho %d can%s.\n", $n,
($n == 1) ? 'e' : 'i';
Il contesto scalare o di lista si propaga verso il secondo o terzo parametro (quello dei due che viene selezionato).
$a = $ok ? $b : $c; # restituisce uno scalare
@a = $ok ? @b : @c; # resistuisce un array
$a = $ok ? @b : @c; # oops, restituisce il numero di elementi!
È possibile utilizzare l'operatore in un'assegnazione se entrambi gli argomenti (il secondo e il terzo) sono lvalue validi (ossia, possono essere utilizzati in un'assegnazione):
($a_o_b ? $a : $b) = $c;
Dal momento che l'operatore produce un risultato assegnabile, usarlo in una assegnazione senza le parentesi può essere fonte di guai. Ad esempio, questo:
$a % 2 ? $a += 10 : $a += 2
Vuol dire in realtà questo:
(($a % 2) ? ($a += 10) : $a) += 2
Invece di questo:
($a % 2) ? ($a += 10) : ($a += 2)
Che dovrebbe probabilmente essere scritto più semplicemente così:
$a += ($a % 2) ? 10 : 2;
``='' è il solito operatore di assegnamento.
Gli operatori di assegnamento funzionano come in C. Cioè,
$a += 2;
equivale a
$a = $a + 2;
although without duplicating any side effects that dereferencing the lvalue
might trigger, such as from tie().[?] Gli altri operatori di assegnamento funzionano in maniera simile.
I seguenti operatori sono validi:
**= += *= &= <<= &&=
-= /= |= >>= ||=
.= %= ^=
x=
Sebbene questi siano raggruppati per famiglia, tutti hanno la precedenza di assegnamento.
Diversamente dal C, l'operatore di assegnamento scalare produce un valore sinistro valido.
Modificare un assegnamento è equivalente a fare un assegnamento e poi modificare la variabile che si era assegnata. Questo è utile per modificare una copia di qualcosa, come questo:
($tmp = $global) =~ tr [A-Z] [a-z];
Così come,
($a += 2) *= 3;
è equivalente a
$a += 2;
$a *= 3;
Analogamente, l'assegnamento di una lista in contesto lista produce la lista di valori sinistri assegnati, e un assegnamento lista in contesto scalare restituisce il numero di elementi prodotti dall'espressione sul lato destro dell'assegnamento.
``,'' è l'operatore binario virgola. In contesto scalare esso valuta il suo argomento a sinistra, ne butta il valore, poi valuta il suo argomento a destra e lo restituisce.
In contesto lista, è il separatore degli argomenti di una lista, e inserisce entrambe i suoi argomenti in una lista.
L'operatore => è un sinonimo dell'operatore virgola, ma forza qualsiasi parola (consistente interamente in caratteri) alla sua sinistra ad esser interpretata come una stringa (dalla 5.001). Questo include parole che potrebbero esser altrimenti esser considerate una costante o una chiamata di funzione.
use constant FOO => "qualcosa";
my %h = ( FOO => 23 );
è equivalente a:
my %h = ("FOO", 23);
Esso NON è:
my %h = ("qualcosa", 23);
Se l'argomento sulla sinistra non è una parola, esso viene prima interpretato come un'espressione, e poi il valore stringa di questa viene usato.
L'operatore => è utile nel documentare la corrispondenza tra chiavi e valori negli hash, ed altri elementi accoppiati nelle liste.
%hash = ( $chiave => $valore );
login( $username => $password );
Sulla lato destro di un operatore lista, esso ha una precedenza molto bassa, tale che esso controlla tutte le espressioni separate da virgola che trova.
Gli unici operatori con precedenza più bassa sono gli operatori logici ``and'', ``or'', e ``not'', i quali possono essere usati per valutare chiamate a opeatori lista senza il bisogno di ulteriori parentesi:
pen HANDLE, "nomefile"
or die "Non posso aprire: $!\n";
Si veda anche la discussione sugli operatori lista in Terms and List Operators (Leftward).
L'operatore unario ``not'' restituisce la negazione logica dell'espressione alla sua destra.
L'operatore binario ``and'' restituisce la congiunzione logica delle due espressioni che lo contornano. è equivalente a && eccetto che per precedenze molto basse. Questo significa che esso corto-circuita: i.e., l'espressione sulla destra viene valutata solo se l'espressione a sinistra è vera.
L'operatore binario ``or'' restituisce la disgiunzione logica tra le due espressioni che lo contornano. è equivalente a || eccetto che per precedenze molto basse. Questo lo rende molto utile per il controllo di flusso
print FH $data or die "Non posso scrivere in FH: $!";
Questo significa che esso cortocircuita: i.e., l'espressione a destra viene valutata solamente se l'espressione a sinistra è falsa. A causa della sua precedenza, dovreste probabilmente evitare di utilizzarlo negli assegnamenti, solo per controllo di flusso.
$a = $b or $c; # bug: questo E<egrave> sbagliato
($a = $b) or $c; # significa veramente questo
$a = $b || $c; # meglio scritto in questo modo
Comunque, quando si trova in un assegnamento in contesto lista e voi state cercando di utilizzare ``||'' per controllo di flusso, probabilmente avrete bisogno di ``or'' in modo che l'assegnamento prende precedenza più alta.
@info = stat($file) || die; # oops, stat in "senso" scalare
@info = stat($file) or die; # meglio, ora @info prende ciE<ograve> che gli spetta
Ma ancora, potreste usare le parentesi.
( @info = stat($file) ) || die; # aggiunto da me
L'operatore binario ``xor'' restituisce l'OR-esclusivo delle due espressioni che lo circondano. Esso non può cortocircuitare ovviamente.
Ecco cosa ha il C che non c'è in Perl:
- & unario
-
Operatore di indirizzo. (Ma date un'occhiata all'operatore ``\'' per ottenere un riferimento.)
- unario
Operatore di dereferenziamento. (I prefessi di dereferenziamento in Perl sono tipati: $, @, %, e &.)
- (TYPE)
-
Mentre solitamente pensiamo ai quote come a dei valori letterali, in Perl essi funzionano come operatori, fornendo varie tipologie di interpolazione e capacità di pattern matching. Perl fornisce caratteri di quote usuali per questi comportamenti, ma vi fornisce anche una strada per scegliere il vostro carattere di quote per uno qualsiasi di essi. Nella seguente tabella, un {} rappresenta una coppia di delimitatori che avete scelto.
Usuale Generico Significato Interpola
'' q{} Letterale no
"" qq{} Letterale sE<igrave>
`` qx{} Comando sE<igrave>*
qw{} Lista di parole no
// m{} Pattern match sE<igrave>*
qr{} Pattern sE<igrave>*
s{}{} Sostituzione sE<igrave>*
tr{}{} Traslitterazione no (ma si veda sotto)
<<EOF here-doc sE<igrave>*
* se il delimitatore non E<egrave> ''.
I delimitatori senza graffe usano lo stesso carattere a prua e a poppa, ma i quattro tipi di parentesi (tonde, angolari, quadrate, graffe) si annideranno tutte, il che significa
q{foo{bar}baz}
è lo stesso che
'foo{bar}baz'
Notate, comunque, che questo non sempre funziona nel quotare codice Perl:
$s = q{ if($a eq "}") ... }; # SBAGLIATO
è un errore di sintassi. Il modulo Text::Balanced (scaricabile da CPAN, e con Perl 5.8 entrato ad esser parte della distribuzione standard) è capace di farlo correttamente.
Ci può essere uno spazio tra l'operatore e i caratteri di quoting, eccetto che quando # è stato usato come carattere di quoting.
q#foo# è parsato come stringa foo, mentre q #foo# è l'operatore q seguito da un commento. Il suo argomento sarà preso dalla prossima linea. Questo vi permette di scrivere:
s {foo} # Rimpiazza foo
{bar} # con bar.
Le seguenti sequenze di escape sono disponibili in costrutti che interpolano e nella traslitterazione.
\t tab (HT, TAB)
\n newline (NL)
\r return (CR)
\f form feed (FF)
\b backspace (BS)
\a alarm (bell) (BEL)
\e escape (ESC)
\033 octal char (ESC)
\x1b hex char (ESC)
\x{263a} wide hex char (SMILEY)
\c[ control char (ESC)
\N{name} named Unicode character
NOTE: Diversamente dal C ed altri linguaggi, Perl non ha la sequenza di escape \v per il tab verticale (VT - ASCII 11).
Le seguenti sequenze di escape sono disponibili in costrutti che interpolano ma non nelle traslitterazioni.
\l rende il carattere successivo lowercase
\u rende il carattere successivo uppercase
\L rende lowercase fino a \E
\U rende uppercase fino \E
\E termina la modifica del case
\Q quota caratteri non-word fino a \E
Se state usando use locale, la mappatura del case [?] usata da \l, \L, \u e \U è presa dal locale corrente. Si veda perllocale.
Se Unicode (per esempio, \N{} o caratteri esadecimali più ampi di 0x100) è stato usato, la mappatura del case usata da \l, \L, \u e \U è come definita dall'Unicode. Per documentazione di \N{name}, si veda charnames.
Tutti i sistemi utilizzano "\n" per rappresentare un terminatore di linea, chiamato ``newline'' (letteralmente ``nuova linea'' N.d.T). Non c'è qualcosa come un invariante, carattere fisico del newline. Esso rappresenta solo un'illusione che il sistema operativo, i driver, le librerie C, e il Perl cospirano a preservare! Non tutti i sistemi leggono "\r" come ASCII CR e "\n" come ASCII LF. Per esempio, su un Mac, questi sono invertiti, e su sistemi senza il terminatore di linea, stampare "\n" potrebbe emettere dati non veri. In generale, usate "\n" quando intendete un ``newline'' per il vostro sistema, ma usate un literal ASCII quando avete bisogno di un carattere esatto. Per esempio, la maggior parte dei protocolli di networking si aspetta e preferisce un CR+LF ("\015\012" o "\cM\cJ") per i terminatori di linea, e sebbene essi spesso accettino anche solo "\012", essi raramente tollerano solo "\015". Se prendete l'abitudine di usare "\n" per il networking, potreste bruciarvi un giorno o l'altro.
Per costrutti che interpolano, variabili che iniziano con ``$'' o ``@'' verranno interpolate. Variabili come $a[3] oppure $href->{key}[0] verranno anch'esse interpolate, così come gli slice (NdT: fette) di array e hash. Ma non le chiamate di metodo come $obj->meth.
Interpolare un array o uno slice interpola gli elementi in ordine, separati dal valore di $", il che è equivalente ad interpolare join $", @array. Array ``Punctuation'' (NdT: array il cui nome e' costituito da segni di interpunzione) come @+ sono interpolati solamente se il nome è racchiuso in parentesi @{+}.
Non potete includere un letterale come $ o @ all'interno di una sequenza \Q. Una sequenza non preceduta da un \ unescaped [?] $ o @ interpola la variabile corrispondente, mentre facendo precedere la sequenza da un \ causerà l'inserimento della stringa letterale \$. Avrete bisogno di scrivere qualcosa come m/\Quser\E\@\Qhost/.
I pattern sono soggetti ad un addizionale livello di interpretazione come le espressioni regolari. Questo viene fatto in un secondo passo, dopo che le variabili sono state interpolate, così che l'espressione regolare può essere incorporata nel pattern dalle variabili. Se non è questo che volete, usate \Q per interpolare una variabile letteralmente.
A parte il comportamento descritto sopra, Perl non espande livelli multipli di interpolazione. In particolare, contrariamente alle aspettative dei programmatori di shell, il back-quote NON interpola all'interno di un doppio quote, e nemmeno i quote singoli impediscono la valutazione delle variabili quando usate all'interno di un doppio quote.[?] rivedere
Ecco gli operatori quote-like che si applicano al pattern matching e ad attivita correlate.
- ?PATTERN?
-
Questo è come
/pattern/, eccetto che trova una corrispondenza solo una volta tra le chiamate all'operatore reset(). Rappresenta una utile ottimizzazione quando volete vedere solo se la prima occorrenza di qualcosa in ciascun file o in un set di file, per esempio. Solo ?? i pattern locali al package corrente sono resettati. [?]
while (<>) {
if (?^$?) {
# linea vuota tra header e body
}
} continue {
reset if eof; # pulisce lo stato di ?? per il prossimo file
}
Questo utilizzo è vagamente deprecato, il che significa che potrebbe possibilmente esser rimosso in qualche versione futura molto lontana di Perl, forse da qualche parte intorno all'anno 2168.
- m/PATTERN/cgimosx
-
- /PATTERN/cgimosx
Cerca una stringa per un pattern match, e in contesto scalare restituisce vero se la corrispondenza è trovata, altrimenti falso. Se nessuna stringa viene specificata attraverso l'operatore
=~ o !~, la ricerca avviene nella variabile $_. (La stringa specificata con =~ non deve essere un lvalue [valore a sinistra di un'espressione, NdT]--potrebbe essere il risultato della valutazione di un'espressione, ma ricordate che =~ crea un legame piuttosto stretto.) Si veda anche perlre. Si veda perllocale per discussioni su considerazioni aggiuntive che scattano quando use locale è in uso.
-
Le opzioni sono:
c Non resetta la posizione di ricerca in seguito ad un match fallito quando si sta utilizzando /g
g Fa match globalmente, i.e. trova tutte le occorrenze.
i Esegue un pattern match case insensitive.
m Tratta le stringhe come linee multiple.
o Compila il pattern solo una volta.
s Tratta la stringa come una singola linea.
x Usa espressioni regolari estese.
Se ``/'' è il delimitatore allota la m iniziale è opzionale. Con m potete usare una coppia di caratteri non alfanumerici e che non siano spazi, come delimitatori. Questo è particolarmente utile quando si sta eseguendo il match di percorsi di nomi che contengono ``/'', per evitare la LTS (leaning toothpick syndrome) [sindrome dello stuzzicadenti pendente, NdT]. Se ``?'' è il delimitatore, allora funziona la regola del match solo una volta di ?PATTERN?.
Se ``''' è il delimitatore, non viene effettuata l'interpolazione sul PATTERN.
PATTERN può contenere delle variabili, le quali saranno interpolate (e il pattern verrà ricompilato) ogni volta che il pattern di ricerca sarà valutato, tranne che quando il il delimitatore è un quote singolo. (Notate che $(, $), e $| non sono interpolati perché assomigliano a dei test di fine stringa.) Se volte che tali pattern siano compilati solo una volta, aggiungete un /o dopo il trailing delimitatore [?]. Questo aggira costose ricompilazioni a run-time, ed è utile quando il valore che state interpolando non cambierà durante il tempo di vita del programma. Comunque, menzionando /o costituisce una promessa che non cambierete le variabili nel pattern. Se le cambiate, Perl non ve lo notificherà . Si veda anche qr/STRING/imosx.
Se PATTERN valuta una stringa vuota, verrà utilizzata l'ultima espressione regolare valutata con successo. In questo caso, solo i flag g e c sul pattern vuoto is honoured [?] - gli altri flag sono presi dal pattern originale. Se non è avvenuto un match precedentemente, questo (silenziosamente) funzionerà come un pattern vuoto genuino (che farà match sempre).
Se l'opzione /g non è utilizzata, m// in contesto lista restituisce una lista che consiste di sottoespressioni che hanno fatto match con le parentesi nel pattern, i.e., ($1, $2, $3...). (Notate che qyu $1 etc. sono anche settati, e che questo è diverso dal comportamento che si aveva in Perl 4.) Quando non ci sono parentesi nel pattern, il valore restituito è la lista (1) per successo [?]. Con o senza parentesi, viene restituita una lista vuota a seguito di un fallimento.
Esempi:
open(TTY, '/dev/tty');
<TTY> =~ /^y/i && foo(); # esegue foo se lo si desidera
if (/Version: *([0-9.]*)/) { $version = $1; }
next if m#^/usr/spool/uucp#;
# un grep "povero"
$arg = shift;
while (<>) {
print if /$arg/o; # compila solo una volta
}
if (($F1, $F2, $Etc) = ($foo =~ /^(\S+)\s+(\S+)\s*(.*)/))
L'ultimo esempio divide $foo nelle prime due parole e nel rimanente della linea, ed assegna questi tre campi a $F1, $F2, ed $Etc. La condizione è vera se qualsiasi delle variabili fosse assegnata, i.e., se il pattern fa match.
Il modificatore /g specifica un pattern matching globale--cioè, fa match più volte possibile all'interno della stringa. Come si comporta dipende dal contesto. In contesto lista, restituisce una lista delle sottostringhe che hanno fatto match, come se ci fossero parentesi intorno all'intero pattern.
In contesto scalare, ciascuna esecuzione di m//g trova il prossimo match, restituendo vero se matcha, e falso se non ci sono ulteriori match. La posizione dopo l'ultimo match può esser letta o settata utilizzando la funzione pos(); si veda perlfunc/pos. Un match che fallisce normalmente resetta la search position [posizione di ricerca, NdT] all'inizio della stringa, ma lo potete evitare con l'aggiunta del modificatore /c (e.g. m//gc). Modificare la stringa target resetta anche la search position.
Potete mescolare il match m//g con m/\G.../g, dove \G è un'asserzione zero-width [ampiezza zero, NdT] che matcha l'esatta posizione dove il precedente m//g aveva lasciato fuori [?]. Senza il moficiatore /g, l'asserzione \G si ancora ancora a pos(), ma il match è ovviamente tentato solamente una volta. Utilizzando \G senza /g su una stringa sulla quale non è stato applicato un match di tipo /g, equivle ad un'asserzione \A che matcha l'inzio della stringa. Notate anche che, attualmente, \G è supportato correttamente sono quando ancorato all'inzio di un pattern.
Esempi:
# list context
($one,$five,$fifteen) = (`uptime` =~ /(\d+\.\d+)/g);
# scalar context
$/ = "";
while (defined($paragraph = <>)) {
while ($paragraph =~ /[a-z]['")]*[.!?]+['")]*\s/g) {
$sentences++;
}
}
print "$sentences\n";
# using m//gc with \G
$_ = "ppooqppqq";
while ($i++ < 2) {
print "1: '";
print $1 while /(o)/gc; print "', pos=", pos, "\n";
print "2: '";
print $1 if /\G(q)/gc; print "', pos=", pos, "\n";
print "3: '";
print $1 while /(p)/gc; print "', pos=", pos, "\n";
}
print "Final: '$1', pos=",pos,"\n" if /\G(.)/;
L'ultimo esempio dovrebbe stampare:
1: 'oo', pos=4
2: 'q', pos=5
3: 'pp', pos=7
1: '', pos=7
2: 'q', pos=8
3: '', pos=8
Final: 'q', pos=8
Notate che l'ultimo match ha matchato q invece di p, lo stesso che un match senza l'ancora \G avrebbe fatto. Notate anche che l'ultimo match non ha aggiornato pos -- pos è aggiornato solamente su un match con /g. Se il match finale ha veramente matchato p, ci sarebbe da scommettere che state utillizzando un Perl più vecchio di pre-5.6.0.
Un utile idioma a mo di legge [?]
$_ = <<'EOL';
$url = new URI::URL "http://www/"; die if $url eq "xXx";
EOL
LOOP:
{
print(" digits"), redo LOOP if /\G\d+\b[,.;]?\s*/gc;
print(" lowercase"), redo LOOP if /\G[a-z]+\b[,.;]?\s*/gc;
print(" UPPERCASE"), redo LOOP if /\G[A-Z]+\b[,.;]?\s*/gc;
print(" Capitalized"), redo LOOP if /\G[A-Z][a-z]+\b[,.;]?\s*/gc;
print(" MiXeD"), redo LOOP if /\G[A-Za-z]+\b[,.;]?\s*/gc;
print(" alphanumeric"), redo LOOP if /\G[A-Za-z0-9]+\b[,.;]?\s*/gc;
print(" line-noise"), redo LOOP if /\G[^A-Za-z0-9]+/gc;
print ". That's all!\n";
}
Ecco qui l'output (diviso in diverse linee):
line-noise lowercase line-noise lowercase UPPERCASE line-noise
UPPERCASE line-noise lowercase line-noise lowercase line-noise
lowercase lowercase line-noise lowercase lowercase line-noise
MiXeD line-noise. That's all!
- q/STRING/
-
'STRING'
-
Una stringa letterale, con quote singolo. Un backslash rappresenta un backslash se non è seguito da un delimitatore o da un altro backslash, in tal caso il delimitatore o backslash viene interpolato.
$foo = q!I said, "Tu dici, 'Lei lo dice.'"!;
$bar = q('Questo E<egrave>.');
$baz = '\n'; # una stringa di due caratteri
- qq/STRING/
-
- ``STRING''
-
Un doppio quote, stringa interpolata.
$_ .= qq
(*** The previous line contains the naughty word "$1".\n)
if /\b(tcl|java|python)\b/i; # :-)
$baz = "\n"; # a one-character string
- qr/STRING/imosx
-
Questo operatore quota (e possibilmente compila) la sua STRING come una espressione regolare. STRING è interpolato nella stesso modo come PATTERN in
m/PATTERN/. Se viene usato ``''' come delimitatore, non viene fatta l'interpolazione. Restituisce una valore Perl che può essere usato al posto della corrispondente espressione /STRING/imosx.
Per esempio,
$rex = qr/my.STRING/is;
s/$rex/foo/;
è equivalente a
s/my.STRING/foo/is;
Il risultato può esser utilizzato come un sotto-pattern in un match:
$re = qr/$pattern/;
$string =~ /foo${re}bar/; # puE<ograve> esser interpolato in altri pattern
$string =~ $re; # oppure usato da solo
$string =~ /$re/; # o in questo modo
Dato che Perl può compilare il pattern al momento dell'esecuzione dell'operatore qr(), utilizzare qr() potrebbe portare a dei vantaggi in termini di velocità in alcune situazioni, specialmente se il risultato di qr() è utilizzato da solo:
sub match {
my $patterns = shift;
my @compiled = map qr/$_/i, @$patterns;
grep {
my $success = 0;
foreach my $pat (@compiled) {
$success = 1, last if /$pat/;
}
$success;
} @_;
}
La precompilazione del pattern in una rappresentazione interna al momento dell'esecuzione di qr() evita il bisogno di ricompilare il pattern ogni volta che si tenta un match /$pat/. (Perl ha molte altre ottimizzazioni interne, ma non sarebbero entrate in gioco nell'esempio sopra se non avessimo usato l'operatore qr().)
Le opzioni sono:
i Do case-insensitive pattern matching.
m Treat string as multiple lines.
o Compile pattern only once.
s Treat string as single line.
x Use extended regular expressions.
Si veda perlre per informazioni aggiuntive sulla sintassi valida per STRING, e per uno sguardo dettagliato alla semantica delle espressioni regolari.
- qx/STRING/
-
- `STRING`
-
Una stringa che viene (possibilmente) interpolata e poi eseguita come un comando di sistema come
/bin/sh o equivalente. Wildcard della shell, pipe e redirezioni saranno onorate (mantenute). L'outputo raccolto viene restituito; lo standard error no. In contesto scalare, ritorna come una singola stringa (potenzialmente multilinea), oppure undef se il comando fallisce. In contesto lista, restituisce una lista di linee (o comunque in base a come avete definito $/ o $INPUT_RECORD_SEPARATOR), o una lista stringa se il comando fallisce.
Dato che il backtick non affligge lo standard error, usate la sintassi di shell per il descrittore di file (supponendo che la shell la supporti) se vi interessa questo. Per catturare lo STDERR e STDOUT di un comando insieme:
$output = `cmd 2>&1`;
Per catturare lo STDOUT ma scartare il suo STDERR:
$output = `cmd 2>/dev/null`;
Per catturare lo STDERR di un comando ma scartare il suo STDOUT (l'ordine qui è importante):
$output = `cmd 2>&1 1>/dev/null`;
Per scambiare lo STDOUT e lo STDERR di un comando in maniera da catturare lo STDERR ma lasciare uscire STDOUT nel vecchio STDERR:
$output = `cmd 3>&1 1>&2 2>&3 3>&-`;
Per leggere sia lo STDOUT e lo STDERR di in comando separatamente, è più facile redirigerli separatamente a dei file, e poi leggerli da questi file quando il programma è terminato:
system("program args 1>program.stdout 2>program.stderr");
Utilizzando un quote singolo come delimitatore protegge il comando dall'interpolazione a doppio quote di Perl, passandolo in una shell invece:
$perl_info = qx(ps $$); # $$
$shell_info = qx'ps $$'; # che E<egrave> il $$ della nuova shell
Come quella stringa venga valutata è affare che riguarda l'interprete del vostro sistema. Sulla maggior parte delle piattaforme, dovrete proteggere i metacaratteri della shell se volete che vengano trattati in maniera letterale. Questo in pratica è difficile da ottenere dato che non è chiaro quali caratteri necessitano di essere escapizzati. Si veda perlsec per un esempio pulito e sicuro dal manuale di fork() ed exec() per emulare il backtick in sicurezza.
Su alcune piattaforme (specialmente quelle DOS-like), la shell potrebbe non esser capace di trattare con comandi multi linea, quindi inserendo dei newline nella stringa potrebbe non darvi quello che vi aspettate. Potete valutare comandi multipli in una linea singola separandoli con il carattere separatore di comando, se la vostra shell lo supporta. (e.g. ; sulla maggior parte delle shell Unix; & sulla shell di Windows NT cmd).
A partire dalla v5.6.0, Perl cercerà di mandare in output tutti i file aperti prima di iniziare il processo figlio, ma questo potrebbe non esser supportato su alcune piattaforme (si veda perlport). Per esser sicuri, potreste aver bisogno di settare $| ($AUTOFLUSH in Inglese) o chiamare il metodo autoslush() di IO::Handle su qualsiasi handle aperto.
Fate attenzione al fatto che alcuni comandi di shell potrebbero porre delle restrizioni sulla lughezza della linea di comando. Dovete assicurarvi che le vostre stringhe non eccadano questo limite dopo le necessarie interpolazioni. Si veda le note specifiche alla piattaforma utilizzata per ulteriori dettagli riguardo al vostro ambiente.
Usare questo operatore può condurre a programmi che sono difficili da portare, dato che i comandi di shell chiamati variano tra i vari sistemi, e potrebbero infatti non esser presenti per niente. Come esempio, il comando type nelle shell POSIX è molto differente dal comando type del DOS. Questo non significa che dovreste uscire dalla vostra strada per aggirare i backtick quando essi sono il modo corretto di fare qualcosa. Perl fu fatto per essere un linguaggio glue [collante, NdT], e una delle cose che lui incolla insieme sono i comandi. Dovete solo capire in cosa vi state muovendo.
Si veda I/O Operators per ulteriori discussioni.
- qw/STRING/
-
Valuta una lista delle parole estratta da STRING, utilizzando uno spazio integrato come delimitatore di parole. Può esser compreso come essere rozzamente equivalente a:
split(' ', q/STRING/);
la differenza sta nel fatto che esso genera una lista reale a tempo di compilazione, e in contesto scalare restituisce l'ultimo elemento della lista. Quindi questa espressione:
qw( foo bar baz )
è semanticamente equivalente alla lista:
'foo', 'bar', 'baz'
Alcuni esempi visti di frequente:
use POSIX qw( setlocale localeconv )
@EXPORT = qw( foo bar baz );
Un errore comune è cercare di separare le parole con una virgola o mettere dei commenti in una stringa multi linea qw. Per questa ragione, la direttiva use warnings e lo switch -w (cioè, la variabile $^W) produce degli avvertimenti se la STRING contiene ``,'' o il carattere ``#''.
- s/PATTERN/RIMPIAZZAMENTO/egimosx
-
Cerca una stringa secondo un pattern, e se lo trova, rimpiazza quel pattern con il testo di rimpiazzamento e restituisce il numero di sostituzioni fatte. Altrimenti restituisce falso (in particolare, la stringa vuota).
Se nessuna stringa viene specificata tramite l'operatore =~ o !~, la ricerca è fatta nella variabile $_ e poi questa viene modificata. (La stringa specificata con =~ deve essere una variabile scalare, un elemento di un array, un elemento di un hash, o l'assegnamento ad uno di questi, i.e., un lvalue.)
Se il delimitatore scelto è un quote singolo, non viene fatta interpolazione nè su PATTERN o su REPLACEMENT. Altrimenti, se il PATTERN contiene un $ che assomiglia ad una variabile anzichè al test di fine stringa, la variabile sarà interpolata nel pattern a run-time. Se volete che il pattern venga compilato solo la prima volta che la variabile è interpolata, usate l'opzione /o. Se il pattern valuta una stringa vuota, verrà utilizzata l'ultima espressione regolare eseguita con successo. Si veda perlre per ulteriori spiegazioni su questo argomento. Si veda perllocale per discussioni su considerazioni addizionali che funzionano quando use locale è in uso.
Le opzioni sono:
e Valuta il lato destro di un'espressione.
g Rimpiazza globalmente, i.e., tutte le occorrenze.
i Esegue un pattern matching case-insensitive.
m Tratta la stringa come linee multiple.
o Compila il pattern solo una volta.
s Tratta la stringa come una linea singola.
x Usa espressioni regolari estese.
Qualsiasi delimitatore non-alfanumerico o che non sia uno spazio potrebbe rimpiazzare lo slash. Se un singolo quote viene utilizzato, non viene fatta un'interpretazione sulla stringa di rimpiazzamento (il modificatore /e sovrascrive questo comportamento, comunque). Diversamente da Perl 4, Perl 5 tratta i backtick come dei normali delimitatori; il testo di rimpiazzamento non viene valutato come un comando. Se il PATTERN è delimitato da quote con parentesi, il RIMPIAZZAMENTO ha la sua personale coppia di quote, che potrebbe essere o no una coppia di parentesi, e.g., s(foo)(bar) oppure s<foo>/bar/. Un /e causerà che la porzione di rimpiazzamento venga trattata come una full-fledged espressione Perl e valutata correttamente e lì [?]. Comunque, la sintassi viene controllata a tempo di compilazione. Un secondo modificatore e causerà un eval sulla porzione di rimpiazzamento prima di esser fatta girare come espressione Perl.
Esempi:
s/\bgreen\b/mauve/g; # don't change wintergreen
$path =~ s|/usr/bin|/usr/local/bin|;
s/Login: $foo/Login: $bar/; # run-time pattern
($foo = $bar) =~ s/this/that/; # copy first, then change
$count = ($paragraph =~ s/Mister\b/Mr./g); # get change-count
$_ = 'abc123xyz';
s/\d+/$&*2/e; # yields 'abc246xyz'
s/\d+/sprintf("%5d",$&)/e; # yields 'abc 246xyz'
s/\w/$& x 2/eg; # yields 'aabbcc 224466xxyyzz'
s/%(.)/$percent{$1}/g; # change percent escapes; no /e
s/%(.)/$percent{$1} || $&/ge; # expr now, so /e
s/^=(\w+)/&pod($1)/ge; # use function call
# expand variables in $_, but dynamics only, using
# symbolic dereferencing
s/\$(\w+)/${$1}/g;
# Add one to the value of any numbers in the string
s/(\d+)/1 + $1/eg;
# This will expand any embedded scalar variable
# (including lexicals) in $_ : First $1 is interpolated
# to the variable name, and then evaluated
s/(\$\w+)/$1/eeg;
# Delete (most) C comments.
$program =~ s {
/\* # Match the opening delimiter.
.*? # Match a minimal number of characters.
\*/ # Match the closing delimiter.
} []gsx;
s/^\s*(.*?)\s*$/$1/; # trim whitespace in $_, expensively
for ($variable) { # trim whitespace in $variable, cheap
s/^\s+//;
s/\s+$//;
}
s/([^ ]*) *([^ ]*)/$2 $1/; # reverse 1st two fields
Notate l'utilizzo di $ invece di \ nell'ultimo esempio. Diversamente da sed, noi usiamo il \digit solamente sul lato sinistro. Da qualsiasi altra parte esso è $<digit>.
Occasionalmente, non potete usare solo un /g per ottenere tutti i cambi che potreste desiderare. Ecco due esempi comuni:
# mette le virgole nel posto corretto in un numero intero
1 while s/(\d)(\d\d\d)(?!\d)/$1,$2/g;
# espande i tab ad una spaziatura 8-colonne
1 while s/\t+/' ' x (length($&)*8 - length($`)%8)/e;
- tr/SEARCHLIST/RIMPIAZZAMENTO/cds
-
- y/SEARCHLIST/RIMPIAZZAMENTO/cds
Traslittera tutte le occorrenze dei caratteri trovati nella lista di ricerca con i corrispondenti caratteri nella lista di rimpiazzamento. Restituisce il numero di caratteri rimpiazzati o cancellati. Se non specificate una stringa attraverso l'operatore =~ o !~, allora verrà traslitterata la stringa $_. (La stringa specificata con =~ deve essere una variabile scalare, un elemento di un array, di un hash, o un assegnamento ad uno di questi, i.e., a lvalue.)
-
Un insieme di caratteri può esser specificato tramite un hyphen [trattino - , N.d.T.], quindi
tr/A-J/0-9/ effettua lo stesso rimpiazzamento di tr/ACEGIBDFHJ/0246813579/. Per i devoti di sed, è possibile usare y come sinonimo di tr. Se la lista di ricerca è delimitata da quote con parentesi, la lista di rimpiazzamento avrà la sua personale coppia di quote, che potrebbero essere o no delle parentesi, e.g., tr[A-Z][a-z] o tr(+\-*/)/ABCD/.
Notate che tr non esegue classi di caratteri di espressioni regolari come \d o [:lower:] [?]. L'operatore tr non è equivalente all'utility tr(1). Se volete mappare stringhe lower/upper case, si veda perlfunc/lc e perlfunc/uc, ed in generale considerate di utilizzare l'operatore s se avete bisogno delle espressioni regolari.
Notate anche che l'idea di insieme di caratteri è ben lontana dall'esser portabile tra i vari set di caratteri--ed anche all'interno degli stessi potrebbe portare a dei risultati che non vi aspettavate. Così ad orecchio è buona norma utilizzare degli insiemi di caratteri che iniziano e finiscono alfabeticamemente con lo stesso case (minuscolo: a-e, maiuscolo: A-E), oppure numeri (0-4). Tutto il resto non è sicuro. Nel dubbio, specificate interamente tutto il set di caratteri.
Options:
c Complementa la lista di RICERCA.
d Cancella i caratteri trovati ma non rimpiazzati.
s Toglie i caratteri duplicati rimpiazzati.
Se specificate il modificatore /c, il set di caratteri della lista di RICERCA viene complementata. Se è specificato il modificatore /d, qualsiasi carattere specificato nella lista di RICERCA non trovato nella lista di RIMPIAZZAMENTO viene cancellato. (Notate che questo è leggermente più flessibile del funzionamento di alcuni programmi tr, i quali cancellano qualsiasi cosa essi trovino nella lista di RICERCA.) Se il modificatore /s viene specificato, le sequenze di caratteri che sarebbero traslitterate allo stesso carattere, vengono ridotte ad una singola istanza di quel carattere.
Se viene usato il modificatore /d, la lista di RIMPIAZZAMENTO viene sempre interpretata come specificato. Altrimenti, se la lista di RIMPIAZZAMENTO è più corta della lista di RICERCA, il carattere finale viene replicato quanto basta. Se la lista di RIMPIAZZAMENTO è vuota, la lista di RICERCA viene replicata. L'ultima cosa è utile per contare i caratteri in una classe o per cancellare sequenze di caratteri in una classe.
Examples:
$ARGV[1] =~ tr/A-Z/a-z/; # porta tutto in minuscolo
$cnt = tr/*/*/; # counta le stelle in $_
$cnt = $cielo =~ tr/*/*/; # counta le stelle nel $cielo
$cnt = tr/0-9//; # counta i numeri in $_
tr/a-zA-Z//s; # bookkeeper -> bokeper
($HOST = $host) =~ tr/a-z/A-Z/;
tr/a-zA-Z/ /cs; # cambia i caratteri non alfabetici in spazi
tr [\200-\377]
[\000-\177]; # cancella l'ottavo bit
Se vengono date più traslitterazioni per un carattere, solo il primo viene utilizzato:
tr/AAA/XYZ/
traslittera qualunque A con una X.
Dato che la tabella di traslitterazione viene costruita a tempo di compilazione, nè la lista di RICERCA, nè la lista di RIMPIAZZAMENTO sono soggetti ad interpolazione con il doppio quote. Il che vuol dire che se usate una variabile, dovete passare per eval():
eval "tr/$vecchialista/$nuovalista/";
die $@ if $@;
eval "tr/$vecchialista/$nuovalista/, 1" or die $@;
- <<EOF
>>
-
Un tipo di quoting orientato alla linea è basato sulla sintassi di shell stile ``here-document''. A seguito di un
<<, specificate una stringa che termina la roba quotata, e tutte le linee che seguono quella corrente fino alla stringa che termina costituiscono il valore di quell'item [elemento, N.d.T.]. La stringa che termina potrebbe esser sia un identificatore (una parola), o del testo quotato. Se quotato, il tipo di quote che utilizzate determina il trattamento del testo, come nel quote normale. Un identificatore non quotato funziona come un quote doppio. Non ci devono essere spazi tra << e l'identificatore, se l'identificatore non è quotato. (Se mettete uno spazio, sarà trattato come identificatore nullo, che è valido, e matcha la prima linea vuota.) La stringa che termina deve esser presente (non quotata e senza spazi intorno) sulla linea che termina
print <<EOF;
Il prezzo E<egrave> $Prezzo.
EOF
print << "EOF"; # lo stesso come sopra
Il prezzo E<egrave> $Prezzo.
EOF
print << `EOC`; # esegue i comandi
echo alto
echo basso
EOC
print <<"foo", <<"bar"; # potete raggrupparli
Ho detto foo.
foo
Ho detto bar.
bar
myfunc(<< "THIS", 23, <<'THAT');
Qui c'E<egrave> una linea
o due.
THIS
e qui un'altra.
THAT
Non vi dimenticate che dovete mettere un punto e virgola alla fine dell'istruzione, Perl non sa che non proverete a fare questo:
print <<ABC
179231
ABC
+ 20;
Se volete che la vostra sintassi here-doc venga indentata con il resto del codice, dovrete rimuovere lo spazio iniziale da ciascuna linea manualmente:
($quote = <<'FINIS') =~ s/^\s+//gm;
The Road goes ever on and on,
down from the door where it began.
FINIS
Se usate here-doc all'interno di un costrutto delimitato, come in s///eg, la roba quotata deve andate tutta dentro il delimitatore finale
Quindi invece di
s/questo/<<E . 'quello'
altro
E
. 'more '/eg;
dovete scrivere
s/questo/<<E . 'quello'
. 'piu'/eg;
altro
E
Se l'identificatore che termina è sull'ultima linea del programma, dovete assicurarvi che ci sia un a capo dopo di esso; altrimenti, Perl vi darà un avvertimento Can't find string terminator ``END'' anywhere before EOF....
Inoltre, le regole di quoting per l'identificatore non sono correlate alle regole di quoting del Perl -- q(), qq(), e simili non sono supportati al posto di '' e "", e la sola interpolazione possibile è per fare backslash del carattere di quote:
print << "abc\"def";
testing...
abc"def
Per chiudere, le stringhe quotate non possono stare su linee multiple. La regola generale è che l'identificatore deve essere una stringa letterale. Attenetevi a questa e dovreste esser al sicuro.
Quando viene presentato con qualcosa che potrebbe avere svariate
interpretazioni, Perl utilizza il principio DWIM (cioè ``Do What I Mean'')
[Fai quello che intendo, N.d.T.] per azzeccare l'interpretazione più
probabile. Questa strategia è cosଠvincente che spesso i programmatori Perl
non sospettano nulla riguardo l'ambivalenza di ciಠche scrivono. Ma da un momento all'altro, le fantasie del Perl differiscono sostanzialmente da quello che l'autore onestamente intendeva.
Questa sezione si auspica di chiarire come Perl gestisce i costrutti quotati.Sebbene la ragione più comune per imparare questo è per districarsi nel labirinto delle espressioni regolari, dato che i passi iniziali del parsing sono gli stessi di quelli degli operatori di quoting, vengono tutti discussi insieme.
La più importante regola di parsing in Perl è la prima discussa qui sotto: quando si processa un costrutto di quoting, Perl prima trova la fine di quel costrutto, poi ne interpreta il suo contenuto. Se capite questa regola, potreste saltare il resto della sezione ad una prima lettura.
Alcuni passi discussi successivamente sono eseguiti concorrentemente, ma dato che i loro risultati sono gli stessi, li consideriamo individualmente. Per costrutti di quoting differenti, Perl esegue un differente numero di passi, da uno a cinque, ma questi passi sono sempre eseguiti nello stesso ordine.
- Trovare la fine
-
Il primo passo è trovare la fine del costrutto quotato, sia che esso
sia un delimitatore multicarattere
"\nEOF\n" nel costrutto <<EOF,
che sia un / che termina un costrutto qq//, un ] che termina
un qq[], o un > che termina un fileglob che inizia con <.
Quando si cerca per delimitatori a singolo carattere non accoppiati,
come /, combinazioni di \\ e \/ vengono saltate. Comunque,
quando si cerca per un delimitatore a singolo carattere accoppiato come
[, le combinazioni di \\, \], e \[ sono tutte saltate, e
i [, ] innestati sono anch'essi saltati. Quando si cerca per delimitatori multicarattere, niente viene saltato.
Per costrutti con delimitatori a tre parti (s///, y///, e tr///),
la ricerca viene ripetuta una volta in più.
Durante questa ricerca, non viene posta attenzione sulla semantica del costrutto.
Quindi:
"$hash{"$foo/$bar"}"
o:
m/
bar # NON un commento, questo slash / termina m//!
/x
non forma un'espressione quotata legale. La parte quotata finisce sul
primo " e /, ed il resto è un errore di sintassi.
Dato che lo slash che termina m// era seguito da un SPACE,
l'esempio sopra non è m//x, ma piuttosto m// senza il modificatore
/x. Quindi il # interno è interpretato come un letterale #.
Anche su \c\ non viene posta attenzione durante questa ricerca.
Quindi il secondo \ in qq/\c\/ è interpretato come una parte di \/,
e il seguente / non è riconosciuto come delimitatore.
Invece, usate \034 o \x1c alla fine del costrutto quotato.
- Rimozione del backslash prima dei delimitatori
-
Durante il secondo passaggio, il testo tra il delimitatore iniziale
e finale è copiato in una locazione sicura, il
\ è rimosso
dalle combinazioni che consistono di \ e il delimitatore--o i delimitatori, cioè entrambi i delimitatori di inizio e di fineiniziano e [?]
Questa rimozione non accade per delimitatori multicarattere.
Notate la combinazione \\ è intatta a sinistra, giusto come era.
Da questo passo, nel parsing non viene usata alcuna informazione sui delimitatori.
- Interpolazione
-
Il prossimo passo è l'interpolazione del testo ottenuto, il quale è ora indipendente dai delimitatori. Ci sono quattro casi differenti.
<<'EOF', m'', s''', tr///, y///
-
Nessuna interpolazione viene effettuata.
'', q//
-
La sola interpolazione è la rimozione di
\ dalla coppia \\.
"", ``, qq//, qx//, <file*glob>
-
\Q, \U, \u, \L, \l (possibilmente accoppiati con \E) sono
convertiti al costrutto Perl corrispondente. Quindi, "$foo\Qbaz$bar"
viene convertito a $foo . (quotemeta("baz" . $bar)) internamente.
Le altre combinazioni sono rimpiazzate con espansioni appropriate.
Ripetiamo che qualsiasi cosa tra \Q e \E
viene interpolata alla stessa maniera. Qualcosa come "\Q\\E" non ha
\E dentro. Invece, ha \Q, \\, e E, cosଠche
il risultato è lo stesso che per "\\\\E". Come regola generale, backslashes tra \Q e \E potrebbero portare a risultati contro intuitivi. Cosà¬,
"\Q\t\E" è convertito a quotemeta("\t"), il quale è lo stesso
come "\\\t" (dato che TAB non è alfanumerico). Notate anche che:
$str = '\t';
return "\Q$str";
potrebbe esser molto vicina all' intenzione congetturale dello scrittore di "\Q\t\E".
Scalari interpolati e array vengono convertiti internamente con gli
operatori di concatenazione join e .. Quindi, "$foo XXX '@arr'"
diventa:
$foo . " XXX '" . (join $", @arr) . "'";
Tutte le operazioni sopra vengono effettuate simultaneamente, da sinistra a destra.
Dato che il risultato di "\Q STRING \E" ha tutti i metacaratteri quotati,
non c'è modo di inserire un letterale $ o @ dentro una coppia \Q\E.
Se protetto da un \, $ sarà quotato e diventa "\\\$"; se no, viene interpretato come l'inizio di uno scalare interpolato.
Notate anche che il codice di interpolazione ha bisogno di prendere una
decisione su dove lo scalare interpolato finisce. Per esempio, sia
"a $b -> {c}" significa realmente:
"a " . $b . " -> {c}";
oppure:
"a " . $b -> {c};
Il più delle volte, il codice più lungo possibile che non
include spazi tra i componenti e che contiene parentesi di match o
quadre, dato che l'esito puಠessere determinato in base
ad un voto euristico degli estimatori, il risultato non è
strettamente predicibile. Fortunatamente, è di solito corretto per
casi ambigui.
?RE?, /RE/, m/RE/, s/RE/foo/,
-
L'elaborazione di
\Q, \U, \u, \L, \l, e l'interpolazione
avviene (quasi) come con il costrutto qq//, ma la sostituzione
di \ seguito da un carattere speciale RE (incluso \) non viene
eseguita. Inoltre, dentro un (?{BLOCK}), (?# comment ), e
un commento # in una espressione regolare con //x, non viene eseguita
alcuna elaborazione. Questo è il primo passo nel quale la presenza
del modificatore //x è rilevante.
L'interpolazione ha diverse stranezze: $|, $(, e $) non vengono
interpolati, e i costrutti $var[SOMETHING] son votati (da estimatori
differenti) ad essere o un elemento di un array o un $var seguito da una RE
alternativa. Questo è il caso nel quale la notazione ${arr[$bar]}
diventa funzionale: /${arr[0-9]}/ è interpretata come l'elemento
dell'array -9, non come un'espressione regolare dalla variabile
$arr seguita da un numero, che sarebbe l'interpretazione di /$arr[0-9]/.
Dato che potrebbe accadere una votazione tra differenti estimatori, il risultato
non è predicibile.
È a questo punto che \1 viene convertito a malincuore a $1
nel testo di rimpiazzo di s/// per correggere gli incorregibili
sed hacker che non hanno ancora fatto loro l'idioma giusto. Un avvertimento
viene emesso se la direttiva use warnings o il flag -w sulla linea di comando
(cioè, la variabile $^W) era settato.
La mancanza di elaborazione di \\ crea delle specifiche restrizioni
sul testo post-processato. Se il delimitatore è /, uno non può
avere la combinazione \/ nel risulato di questo step. / terminer&agreve;
l'espressione regolare, \/ sarà ripulita in / nello step precedente,
e \\/ verrà lasciato come è. Dato che / è
equivalente a \/ dentro ad un'espressione regolare, questo non importa se il
delimitatore non è un carattere speciale per il motore RE, come in
s*foo*bar*, m[foo], o ?foo?; o un carattere alfanumerico, come in:
m m ^ a \s* b mmx;
Nella RE sopra, che è intenzionalmente offuscata per illustrare l'esempio,
il delimitatore è m, il modificatore è mx, e dopo che il
backslash viene rimosso, la RE è la stessa come per m/ ^ a \s* b /mx.
C'è più di una ragione che vi ha incoraggiato a restringere
i vostri delimitatori a scelte non-alfanumeriche e con senza spazi vuoti.
Questo passo è l'ultimo per tutti i costrutti tranne che le
espressioni regolari, le quali vengono elaborate più avanti.
- Interpolazione di espressioni regolari
-
I passi precedenti venivano eseguiti durante la compilazione del codice Perl,
ma questo avviene a tempo di esecuzione--sebbene potrebbe esser ottimizzato
ad esser calcolato a tempo di compilazione se opportuno. Dopo la pre-elaborazione
descritta sopra, e possibilmente dopo la valutazione se sono coinvolti concatenazione, unione,
traduzione dei case [delimitatori, N.d.T.], o il mataquoting, la stringa risultante
viene passata al motore RE per la compilazione.
Qualunque cosa accada nel motore RE potrebbe esser discusso meglio in perlre,
ma per ragioni di continuità, dobbiamo farlo anche qui.
Questo è un altro passo nel quale la presenza del modificatore //x
è rilevante. Il motore RE scansiona la stringa da sinistra a destra e
la converte in un automa finito.
I caratteri con backslash sono o rimpiazzati con le stringhe letterali
corrispondenti (come con \{), o altrimenti essi generano dei nodi
speciali nell'automa finito (come con \b). I caratteri speciali per
il motore RE (come |) generano i nodi corrispondenti o gruppi di nodi.
Commenti come (?#...) vengono ignorati. Tutto il resto viene o
convertito a delle stringhe letterali per match, o altrimenti viene
ignorato (come è per lo spazio vuoto e i commenti stile # se
//x è presente).
Il parsing del costrutto a parentesi quadre, è piuttosto
differente rispetto alle regole utilizzate per il resto del pattern.
Il terminatore di questo costrutto viene trovato utilizzando le stesse
regole come per trovare il terminatore di un costrutto delimitato da {},
l'unica eccezione è ] che essendo immediatamente seguito da [
viene trattato come preceduto da un backslash. In maniera simile, il terminatore
(?{...}) viene trovato usando le stesse regole come per trovare il terminatore
di un costrutto delimitato da {}.
È possibile ispezionare sia la stringa data al motore RE che l'automa
finito risultante. Vedere gli argomenti debug/debugcolor
nella direttiva use re, così come per lo switch -Dr sulla
linea di comando di Perl in perlrun/``Command Switches''.
- Ottimizzazioni delle espressioni regolari
-
Questo passo è elencato solo per completezza. Dato che esso
non cambia le semantiche, i dettagli di questo passo non sono documentati
e sono soggetti a cambiamenti senza notifica. Questo passo viene eseguito
dopo che l'automa finito era generato durante il passo precedente.
È a questo punto che split() ottimizza silenziosamente /^/
a /^/m.
Ci sono diversi operatori di I/O dei quali dovreste sapere qualcosa.
Una stringa racchiusa da backtick (accenti gravi) prima subisce una
interpolazione a doppio quote. Poi viene interpretata come un comando
esterno, e l'output di quel comando è il valore della stringa
di backtick, come in una shell. In contesto scalare, viene restituita
una stringa singola che consiste di tutto l'output. In contesto lista,
viene restituita una lista di valori, uno per linea di output. (Potete settare
$/ per utilizzare un differente terminatore di linea). Il comando
viene eseguito ogni volta che lo pseudo-letterale viene valutato.
Il valore di stato del comando viene restituito in $? (si veda perlvar
per l'interpretazione di $?). Diversamente da csh, non viene
effettuata una traduzione sui dati restituiti--gli a capo rimangono a capo.
Diversamente dalle altre shell, i quote singoli non nascondono i nomi di
variabili nel comando per l'interpretazione. Per passare un segno
letterale di dollaro attraverso la shell, avete bisogno di nasconderla
con un backslash. La forma generalizzata dei backtick e qx//. (Perchè
i backtick vengono sempre sottoposti ad espansione da parte della shell,
si veda perlsec per problemi di sicurezza).
In contesto scalare, valutare un filehandle in parentesi angolari raccoglie
la prossima linea da quel file (ritorno a capo incluso), o undef alla fine
del file o a causa di un errore. Quando $/ è settato ad undef
(a volte conosciuto come modalità file-slurp) e il file è vuoto,
esso ritorno '' la prima volta, seguito successivamente da un undef.
Di solito dovete assegnare il valore restituito ad una variabile, ma c'è
una situazione nella quale accade un assegnamento automatico. Se e solo se
il simbolo in input è la sola cosa dentro la condizione di un while
(anche se travestito da for(;;)), il valore viene automaticamente assegnato alla
variabile globale $_, distruggento qualsiasi cosa fosse lì precedentemente.
(Questa vi potrebbe sembrare una cosa strana, ma userete questo costrutto in quasi
tutti gli script Perl che scriverete). La variabile $_ non viene localizzata implicitamente.
Dovrete mettere un local $_; prima del ciclo se volete che accada.
Le linee seguenti sono equivalenti:
while (defined($_ = <STDIN>)) { print; }
while ($_ = <STDIN>) { print; }
while (<STDIN>) { print; }
for (;<STDIN>;) { print; }
print while defined($_ = <STDIN>);
print while ($_ = <STDIN>);
print while <STDIN>;
Questo anche si comporta in maniera simile, ma aggira $_ :
while (my $line = <STDIN>) { print $line }
In questi costrutti ciclici, il valore assegnato (se l'assegnamento
è automatico o esplicito) viene testato per vedere se esso
è definito. Il test defined aggira i problemi nei quali la linea
ha un valore stringa che sarebbe trattato come falso dal Perl,
per esempio un ``'' o un ``0'' senza ritorno a capo. Se veramente volete
terminare il ciclo per quei valori allora dovrete testarli esplicitamente:
while (($_ = <STDIN>) ne '0') { ... }
while (<STDIN>) { last unless $_; ... }
In altri contesti booleani, <filehandle senza un test
esplicito defined o un confronto, verrà segnalato
un avvertimento se la direttiva use warnings o lo switch -w
sulla linea di comando (la variabile $^W) sono utilizzati.
I filehandle STDIN, STDOUT, e STDERR sono predefiniti. (I filehandle
C<stdin>, C<stdout>, e C<stderr> funzioneranno anche eccetto che nei
package, dove verrebbero interpretati come identificatori locali
anzichE<egrave> globali). Dei filehandle addizionai possono esser creati
con la funzione open(), tra le altre cose. Si veda L<perlopentut> e
L<perlfunc/open> per dettagli su questo.
X<stdin> X<stdout> X<sterr>
Se un <FILEHANDLE> è usato in un contesto che sta cercando per
una lista, viene restituita una lista comprendente tutte le linee di input,
una linea per ciascun elemento della lista. È facile crescere ed ottenere
un insieme di dati molto grande in questo modo, quindi usatelo con attenzione.
<FILEHANDLE> potrebbe anche esser scritto come readline(*FILEHANDLE).
Si veda perlfunc/readline.
Il filehandle nullo <> è speciale: puಠesser usato per emulare
il comportamento di sed e awk. L'input da <> viene o dallo standard
input, o da ciascun file listato sulla linea di comando. Ecco come funziona:
la prima volta che <> viene valutato, l'array @ARGV viene controllato, e se
è vuoto, $ARGV[0] viene settato a ``-'', cosଠche quando viene aperto, vi
da lo standard input. Poi l'array @ARGV viene processato come una lista di
nomi di file. Il ciclo
while (<>) {
... # codice per ciascuna linea
}
è equivalente al seguente pseudo codice stile Perl:
unshift(@ARGV, '-') unless @ARGV;
while ($ARGV = shift) {
open(ARGV, $ARGV);
while (<ARGV>) {
... # code for each line
}
}
eccetto il fatto che non è cosଠscomodo da scrivere, e funziona veramente.
Esegue davvero lo shift sull'array @ARGV e mette il nome di file corrente
dentro la variabile $ARGV. Internamente esso utilizza anche il filehandle ARGV
--<> è solamente un sinonimo per <ARGV>, che è magico. (Lo pseudo codice sopra
non funziona perché tratta <ARGV> come non-magico.)
Potete modificare @ARGV prima del primo <> affinchè l'array finisca col contenere
la lista dei nomi di file che volete veramente. I numeri di linea ($.) continuano
a crescere file dopo file anche se l'input fosse un file molto grande.
Si veda l'esempio in perlfunc/eof per capire come resettare i numeri di linea in ogni file.
Se volete settare @ARGV alla vostra lista di file, modificatelo in anticipo.
Questo inserisce in @ARGV tutti file di testo con codifica ASCII se non viene dato @ARGV:
@ARGV = grep { -f && -T } glob('*') unless @ARGV;
Potete anche settarli ad una pipe di comandi. Per esempio, questo filtra
automaticamente i file compressi, passati come argomento, tramite gzip:
@ARGV = map { /\.(gz|Z)$/ ? "gzip -dc < $_ |" : $_ } @ARGV;
Se volete passare degli switch (le opzioni da riga di comando come --verbose, N.d.T.)
ai vostri script, potete utilizzare uno dei moduli Getopt o inserire davanti un ciclo
come questo:
while ($_ = $ARGV[0], /^-/) {
shift;
last if /^--$/;
if (/^-D(.*)/) { $debug = $1 }
if (/^-v/) { $verbose++ }
# ... # other switches
}
while (<>) {
# ... # code for each line
}
Il simbolo <> restituirà undef alla fine del file solo una volta.
Se lo chiamate ancora una volta dopo di questo, esso assumerà che stiate
processando un'altro array @ARGV, e se non avete settato @ARGV, leggerà
l'input da STDIN.
Se quello che le parentesi angolari contengono è semplicemente una
variabile scalare (per esempio, <$foo>), allora quella variabile contiene
il nome del filehandle dal quale verrà letto l'input, o il suo typeglob, o
un riferimento allo stesso. Per esempio:
$fh = \*STDIN;
$line = <$fh>;
Se quello che sta tra le parentesi angolari non è nè un filehandle nè
una semplice variabile scalare contenente il nome di un filehandle, typeglob,
o riferimento a typeglob, allora viene interpretato come il modello di un
nome di file da esser espanso, e o una lista di nomi di file o il prossimo
nome di file nella lista viene restituito, a seconda del contesto. Questa
distinzione è determinata su base sintattica. Cioè <$x> è sempre una
readline() da un handle indiretto, ma <$hash{key}> è sempre un glob().
Questo perché $x è una semplice variabile scalare, ma $hash{key} no--è
un elemento di hash. Anche <$x > (notate lo spazio extra)
è trattato come glob("$x "), non come readline($x).
Un livello di interpretazione a doppio quote viene fatto prima, ma non potete
dire <$foo> perché questo è un filehandle indiretto come spiegato nel
paragrafo precedente. (Nelle versioni più vecchie di Perl, i programmatori
inserirebbero delle parentesi graffe per forzare l'interpretazione come glob
di nome di file: <${foo}>. Oggi, viene considerato più pulito chiamare
la funzione interna direttamente come glob($foo), che probabilmente è la
via giusta per farlo.) Per esempio:
while (<*.c>) {
chmod 0644, $_;
}
è equivalente all'incirca a:
open(FOO, "echo *.c | tr -s ' \t\r\f' '\\012\\012\\012\\012'|");
while (<FOO>) {
chomp;
chmod 0644, $_;
}
eccetto che il glob viene fatto internamente utilizzando l'estensione standard
File::Glob. Naturalmente, la via più corte per fare quanto sopra è:
chmod 0644, <*.c>;
Un (file)glob valuta il suo argomento (interno) solo quando sta iniziando
una nuova lista. Tutti i valori devono esser letti prima che inizi un'altra volta.
In contesto lista, questo non è importamente perché li ottenete comunque tutti.
Tuttavia, in contesto scalare l'operatore restituisce il prossimo valore ogni volta
che viene chiamato, oppure undef quando la lista è finita. Come con la lettura
dei filehandle, viene generato un automatico defined quando il glob capita nella parte
di test del while, perché la restituzione di un glob legale (ad esempio un file chiamato 0)
terminerebbe altrimenti il ciclo. Ancora, undef viene restituito solo una volta. Cosଠse
vi state aspettando un solo valore da un glob, è molto meglio dire
($file) = <blurch*>;
che
$file = <blurch*>;
perché l'ultimo alternerebbe la restituizione di un nome di file con un valore falso.
Se state cercando di fare l'interpolazione di una variabile, è definitivamente
meglio usare la funzione glob(), perché la vecchia notazione potrebbe confondere
le persone con la notazione a filehandle indiretto.
@files = glob("$dir/*.[ch]");
@files = glob($files[$i]);
Come il C, Perl esegue un certo numero di valutazioni di espressioni
a tempo di compilazione ogni volta che determina che tutti gli argomenti
di un operatore sono statici e non hanno effetti collaterali. In particolare,
la concatenazione di una stringa avviene a tempo di compilazione tra dei letterali
che non fanno una sostituzione variabile. Anche l'interpolazione del backslash
avviene a tempo di compilazione, Potete dire
'Ora E<egrave> il momento per tutte' . "\n" .
'le brave persone di venire a.'
e tutto questo si riduce ad una stringa internamente. Allo stesso modo,
se dite
foreach $file (@filenames) {
if (-s $file > 5 + 100 * 2**16) { }
}
il compilatore pre-calcolerà il numero che quell'espressione
rappresenta in maniera che non debba farlo l'interprete.
Perl non ha ufficialmente un operatore no-op, ma le semplici costanti
0 e 1 sono casi speciali che non producono degli avvertimenti
in constesto void (vuoto, N.d.T.), cosଠche potete fare in modo sicuro
1 while foo();
Stringhe di bit di qualunque dimensione possono esser manipolati
dagli operatori di bit su stringhe (~ | & ^).
Se gli operandi di un operatori di bit binario sono delle stringhe
di dimensioni differenti, gli operatori | e ^ funzionano come se
l'operando più corto avesse dei bit settati a zero sulla destra,
mentre l'opeartore & funziona come se l'operando più lungo fosse
troncato alla lunghezza di quello più corto. La granularità per questo
tipo di estensione o troncamento è uno o più byte.
# esempio basato su ASCII
print "j p \n" ^ " a h"; # stampa "JAPH\n"
print "JA" | " ph\n"; # stampa "japh\n"
print "japh\nJunk" & '_____'; # stampa "JAPH\n";
print 'p N$' ^ " E<H\n"; # stampa "Perl\n";
Se state intendendo che volete manipolare stringhe di bit, siate
certi che state fornendo stringhe di bit: se un operando è un numero,
ciಠimplicherà una operazione di bit numerica. Potreste esplicitamente
mostrare che tipo di operazione intendete utilizzando "" o 0+, come
nell'esempio qui sotto.
$foo = 150 | 105; # produce 255 (0x96 | 0x69 E<egrave> 0xFF)
$foo = '150' | 105; # produce 255
$foo = 150 | '105'; # produce 255
$foo = '150' | '105'; # produce la stringa '155' (sotto ASCII)
$baz = 0+$foo & 0+$bar; # entrambi gli opearndi sono esplicitamente numerici
$biz = "$foo" ^ "$bar"; # entrambi gli opearndi sono esplicitamente delle stringhe
Si veda perlfunc/vec per informazioni su come manipolare bit singoli in un vettore di bit.
Di default, Perl assume di dover eseguire gran parte delle operazioni
aritmetiche in virgola mobile. Ma dicendo
use integer;
potete dire al compilatore che va bene utilizzare le operazioni intere
(se se la sente) da qui alla fine del BLOCK.
Un blocco innestato potrebbe revocare ciಠdicendo
no integer;
che dura fino alla fine di quel BLOCK. Notate che questo non vuol dire che
tutto è solamente un intero, meramente che Perl puಠusare operazioni intere
se se la sente. Per esempio, anche sotto use integer, se usate sqrt(2),
otterrette ancora 1.4142135623731 o simili.
Usato sui numeri, gli operatori sui bit (``&'', ``|'', ``^'', ``~'', ``<<'',
e ``>>'') producono sempre risultati interi. (Ma date un'occhiata anche
Operatori di bit su stringhe.) Comunque, use integer ha ancora senso per essi.
Di default, i loro risultati sono interpretati come interi senza segno,
ma se use integer è in azione, i loro risultati sono interpretati come interi con segno.
Per esempio, ~0 solitamente fa una valutazione ad un valore intero grande.
Tuttavia, use integer; ~0 è -1 su macchine a complemento a due.
Mentre use integer fornisce solamente aritmetica per interi, non
c'è un meccanismo analogo per fornire arrotondamento automatico
o troncamento a un certo numero di cifre decimali. Per arrotondare ad un certo
numero di cifre, sprintf() o printf() sono solitamente la via più semplice.
Si veda perlfaq4.
I numeri in virgola mobile sono solo delle approssimazioni a qualcosa che
un matematico chiamerebbe numeri reali. Ci sono infiniti numeri reali rispetto
ai float, quindi alcuni spigoli devono esser smussati. Per esempio:
printf "%.20g\n", 123456789123456789;
# produces 123456789123456784
Fare il test di uguaglianza o disuguaglianza per un numero in virgola mobile
non è una buona idea. Qui presentiamo un (relativamente costoso)
trucco per confrontare se due numeri in virgola mobile sono uguali rispetto
un particolare numero di cifre decimali. Si veda Knuth, volume II, per un
trattamento più robusto di questo argomento.
sub fp_equal {
my ($X, $Y, $POINTS) = @_;
my ($tX, $tY);
$tX = sprintf("%.${POINTS}g", $X);
$tY = sprintf("%.${POINTS}g", $Y);
return $tX eq $tY;
}
Il modulo POSIX (parte della distribuzione standard del Perl) implementa
ceil(), floor(), e altre funzioni matematiche e trigonometriche.
Il modulo Math::Complex (parte della distribuzione standard del Perl)
definisce delle funzioni matematiche che funzionano sia sui reali che
sui numeri immaginari. Math::Complex non così efficiente come POSIX,
ma POSIX non può funzionare con i numeri complessi.
L'arrotondamento in applicazioni finanziarie ha serie implicazioni, e
il metodo di arrotondamento utilizzato dovrebbe esser specificato precisamente.
In questi casi, esso paga il fatto di non fidarsi di qualsiasi sistema di
arrotondamento venga utilizzato dal Perl, ma invece di implementare la
funzione di arrotondamento di c [?] -_-
I moduli standard Math::BigInt and Math::BigFloat forniscono
operatori aritmetici a precisione variabile operatori overloaded operatori, sebbene
attualmente sono abbastanza lenti. Al costo di un po' di spazio e di
una considerevole perdita in velocità , vi evitano le trappole associate con
rappresentazioni a precisione limitata.
use Math::BigInt;
$x = Math::BigInt->new('123456789123456789');
print $x * $x;
# prints +15241578780673678515622620750190521
Ci sono diversi moduli che vi permettono di eseguire calcoli con (limitati
solo da memoria e tempo di cpu) precisione illimitata o fissa. Ci sono anche
dei moduli non standard che forniscono delle implementazioni più veloci
attraverso librerie C esterne.
Segue un corto, ma incompleto sommario:
Math::Fraction grandi, illimitate frazioni come 9973 / 12967
Math::String tratta sequenze di numeri come stringhe
Math::FixedPrecision calcola con precisione fissa
Math::Currency per calcoli monetari
Bit::Vector manipola vettori di bit velocemente (usa il C)
Math::BigIntFast e` un wrapper a Bit::Vector per numeri grandi
Math::Pari fornisce accesso alla libreria Pari C
Math::BigInteger usa una libreria C esterna
Math::Cephes usa la libreria Cephes C (non per numeri grandi)
Math::Cephes::Fraction frazioni attraverso la libreria Cephes
Math::GMP un altro che usa una libreria C esterna
Scegliete con buon senso.
La versione su cui si basa questa traduzione è ottenibile con:
perl -MPOD2::IT -e print_pod perlop
Per maggiori informazioni sul progetto di traduzione in italiano si veda
http://pod2it.sourceforge.net/ .
Traduzione a cura di Daniele Ludovici.
Revisione a cura di .
Wed Jan 28 14:17:56 2009
|