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 .
La 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.
Gli 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 (associativita` 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. Si veda
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 da una
parentesi aperta come simbolo 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($pippo, exit); # Decisamente non e` cio` che si vuole.
print $pippo, exit; # Neanche questo.
# Queste eseguono print prima di valutare exit:
(print $pippo), exit; # Questo e` cio` che si vuole.
print($pippo), exit; # Oppure questo.
print ($pippo), exit; # O anche questo.
Si noti anche che
print ($pippo & 255) + 1, "\n";
probabilmente non fa ciò che di primo acchito ci si
aspetterebbe. Le parentesi racchiudono la lista di argomenti per
print , che viene valutato (e stampa il risultato di $pippo &
255 ). Poi viene aggiunto uno al valore restituito da print
(solitamente 1). Il risultato è una cosa simile a:
1 + 1, "\n"; # Ovviamente non e` quello che si intendeva.
Per ottenere il risultato corretto bisogna scrivere:
print(($pippo & 255) + 1, "\n");
Per un ulteriore approfondimento si veda anche Operatori unari con nome.
Vengono interpretati come termini anche i costrutti do {} ed eval{} , le chiamate a subroutine e
metodi, e i costruttori anonimi [] e {} .
Si veda anche Operatori per il quote ed equivalenti 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 [hard reference, NdR] o
simbolico [symbolic reference, NdR] 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). Si vedano perlreftut e perlref.
In caso contrario, 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 a cui è stato applicato bless ) oppure un nome
di una classe (ossia il nome di un package). Si veda 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
Si noti che, come in C, Perl non definisce quando la variabile è
incrementata o decrementata. Basta sapere che sarà fatto una volta
prima o dopo il valore restituito. Questo significa anche che modificare
una variabile due volte nella stessa istruzione porterà ad un comportamento indefinito.
Si evitino istruzioni come:
$i = $i ++;
print ++ $i + $i ++;
Perl non garantisce quale sia il risultato delle istruzioni di cui sopra.
L'operatore di auto-incremento ha un po' di magia in più. Se viene
incrementata una variabile numerica, o che sia stata usata in contesto
numerico, si ottiene un normale incremento. Se, tuttavia, la variabile è
stata utilizzata solo in un contesto di stringa fin dalla sua impostazione, e contiene
un valore che non è la stringa vuota e corrisponde allo schema
/^[a-zA-Z]*[0-9]*\z/ , allora l'incremento viene fatto considerandola stringa,
conservando ciascun carattere entro il suo intervallo, con eventuale riporto al
carattere successivo:
print ++($pippo = '99'); # stampa '100'
print ++($pippo = 'a0'); # stampa 'a1'
print ++($pippo = 'Az'); # stampa 'Ba'
print ++($pippo = '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 vuol dire -(2**4), non (-2)**4. È
implementato utilizzando la funzione C pow(3) , che internamente
utilizza dei numeri in virgola mobile.
Il ``! '' unario effettua una negazione logica, ossia ``non''. Per una versione dello stesso operatore
con precedenza più bassa si veda anche not .
Il ``- '' unario effettua una negazione aritmetica se l'operando
è numerico. Se l'operando è un identificatore, viene
restituita una stringa che consiste nel segno meno seguito
dall'identificatore. Diversamente, 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 alla stringa "-pippo" . Se, però, la stringa
comincia con con carattere non alfabetico (a parte + o - ), Perl
proverà a convertirla in un valore numerico ed effettuare la negazione
aritmetica. Se la stringa non può essere convertita
correttamente in un valore numerico, Perl emetterà l'avviso Argument
``the string'' isn't numeric in negation (-) at ... [L'argomento ``stringa'' non
è numerico nella negazione (-) alla riga..., NdT].
Il ``~ '' unario effettua una negazione bit a bit, ossia il
complemento ad 1. Ad esempio, 0666 & ~027 è uguale a 0640
(si veda anche Aritmetica Intera e Operatori bit a bit su stringhe).
Va notato 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 tra parentesi che sarebbe altrimenti interpretata come
lista dei parametri della funzione (si vedano gli esempi sopra alla voce
Termini e operatori di lista (associatività a sinistra)).
Il ``\ '' unario crea un riferimento a tutto ciò che segue. Si vedano
perlreftut e perlref. Quest'operazione non va confusa con l'utilizzo
della backslash all'interno di stringhe, per
quanto entrambe le forme esprimono il concetto di proteggere
ciò che segue dall'interpolazione del loro valore.
Il ``=~ '' binario effettua un pattern match su un'espressione scalare.
Di default, alcune operazioni agiscono su, o modificano, la stringa contenuta in $_.
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 di lista dipende dalla singola operazione. Per i dettagli si veda
Operatori Quote-Like per Espressioni Regolari.
Se l'argomento di destra è un'espressione invece di un pattern di ricerca,
sostituzione o traslitterazione, viene interpretato come pattern di ricerca a tempo di
esecuzione.
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).
Va notato che se si sta utilizzando la direttiva integer , l'operatore ``%'' utilizza direttamente
il corrispondente operatore C, come questo viene 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 di lista,
se l'operando di sinistra è posto fra parentesi, ripete la lista. Se l'operando di
destra è zero o negativo, restituisce una stringa vuota o una lista vuota, a seconda del
contesto.
print '-' x 80; # stampa una riga di trattini
print "\t" x ($tab/8), ' ' x ($tab%8); # [sostituisce spazi con tab]
@uni = (1) x 80; # una lista di 80 '1'
@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 spostato a sinistra del numero di
bit specificato dall'operando di destra. Gli operandi devono essere interi (Si veda anche
Aritmetica intera).
Il ``>>'' binario restituisce il valore dell'operando di sinistra spostato a destra del numero di
bit specificato dall'operando di destra. Gli operandi devono essere interi (Si veda anche
Aritmetica intera).
Si noti che sia ``<<'' che ``>>'' sono implementati in Perl utilizzando
direttamente i corrispondenti operatori C. Se si sta utilizzando use integer
(si veda Aritmetica intera) vengono utilizzati gli interi con segno del C, altrimenti vengono
utilizzati interi senza segno. In entrambi i casi, l'implementazione non
genererà risultati che siano maggiori della dimensione degli interi con i quali il
Perl è stato compilato (32 o 64 bit).
Il risultato di oltrepassare il limite consentito per gli interi non è definito,
poiché non è definito neanche in C. In altre parole, usando interi 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 le parentesi
opzionali.
Se un qualunque operatore di lista (print(), ecc.) o qualunque operatore unario
(chdir(), ecc.) È seguito da una parentesi come simbolo 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 $pippo || die; # (chdir $pippo) || die
chdir($pippo) || die; # (chdir $pippo) || die
chdir ($pippo) || die; # (chdir $pippo) || die
chdir +($pippo) || die; # (chdir $pippo) || die
ma, dato che * ha precedenza maggiore rispetto agli operatori con nome:
chdir $pippo * 20; # chdir ($pippo * 20)
chdir($pippo) * 20; # (chdir $pippo) * 20
chdir ($pippo) * 20; # (chdir $pippo) * 20
chdir +($pippo) * 20; # chdir ($pippo * 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 (a sinistra).
=head2 Operatori di confronto
X<relational operator> X<operator, relational>
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 i NaNs (not-a-number) [non un numero, NdR] come valori numerici, usando
questi con ``<=>'' restituisce undef. NaN non è ``<'', ``=='', ``>'', ``<='' o
``>='' a qualsiasi cosa (anche NaN), quindi questi 5 restituiscono falso. NaN != NaN restituisce
un valore vero, così come 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" 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 a 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.
Se è abilitato use locale , ``lt'', ``le'', ``ge'', ``gt'' e ``cmp'' usano l'ordinamento
specificato dal locale corrente. Si veda anche perllocale.
L'operatore binario ``&'' restituisce l'AND bit a bit dei suoi operandi.
(Si vedano anche Aritmetica Intera e Operatori bit a bit su stringhe).
Va notato che ``&'' ha priorità minore degli operatori di confronto, per esempio le
parentesi sono essenziali in un test come
print "uguale\n" if ($x & 1) == 0;
L'operatore binario ``|'' restituisce l'OR bit a bit dei suoi operandi.
(Si vedano anche Aritmetica Intera e Operatori bit a bit su stringhe).
L'operatore binario ``^'' restituisce lo XOR bit a bit dei suoi operandi.
(Si vedano anche Aritmetica Intera e Operatori bit a bit su stringhe).
Va notato 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ò significa che, se l'operando a sinistra è falso, l'operando a destra non
viene nemmeno valutato. Se avviene tale valutazione dell'operando, il contesto scalare o
quello di lista viene propagato sulla valutazione dell'operando a destra.
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 restituisce 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 è vero, l'operatore a
destra non sarà valutato. Se avviene tale valutazione dell'operando il contesto
scalare o quello di lista viene propagato sulla valutazione del secondo operando.
Gli operatori || e && restituiscono l'ultimo valore valutato
(diversamente dal || e il && del C, i quali restituiscono 0 o 1). Quindi, un modo
ragionevolmente portabile di scoprire la propria directory home potrebbe essere:
$home = $ENV{'HOME'} || $ENV{'LOGDIR'} ||
getpwuid($<))[7] || die "Sei senza casa!\n";
In particolare, questo significa che non si deve utilizzare questo metodo
per la selezione tra due valori non scalari (array o hash):
@a = @b || @c; # questo e` sbagliato
@a = scalar(@b) || @c; # in realta` si intendeva dire questo
@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 afferra(), next LINE;
Con gli operatori stile C questo sarebbe stato scritto così:
unlink("alpha", "beta", "gamma")
|| (afferra(), next LINE);
Usare ``or'' per l'assegnamento è improbabile che faccia ciò
che si vuole; si veda sotto.
L'operatore binario ``..'' è l'operatore di intervallo, che si comporta davvero come
due operatori differenti in base al contesto di utilizzazione. In
contesto di lista, restituisce 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 intervallo è utile per
scrivere cicli tipo foreach (1..10) e per fare operazioni di slice sugli array.
Nell'implementazione corrente, quando l'operatore di intervallo viene utilizzato come espressione nei
cicli di tipo foreach , non viene creato alcun array temporaneo, ma nelle versioni più vecchie
di Perl si potrebbe sprecare molta memoria quando si scrive qualcosa come questo:
for (1 .. 1_000_000) {
# code
}
L'operatore di intervallo funziona anche sulle stringhe, quando viene usato l'auto-incremento magico,
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 stato
booleano personale. Esso è falso finché il suo operando a sinistra
è falso. Una volta che l'operando a sinistra diventa vero, l'operatore di intervallo rimane
vero finché l'operando a destra è vero, DOPODICHÉ l'operatore di intervallo
diventa falso di nuovo. Non diventa falso fino alla prossima volta in cui viene valutato l'operatore di
intervallo. Esso può testare l'operando a 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
correttamente come fa ``..''.
L'operando a destra non viene valutato quando l'operatore si trova nello stato di falso, e
l'operando a 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 reimpostato per ogni
intervallo incontrato. Il numero di sequenza finale in un intervallo, ha aggiunta in coda la stringa
``E0'', la quale non altera il suo valore numerico, ma vi offre un qualcosa di utile per cercarla se
volete escludere il punto di terminazione. 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 numero di riga di input corrente (la variabile
$. ).
Per essere pignoli, il confronto è realmente int(EXPR) == int(EXPR) , ma è
realmente un problema se si usa un'espressione in virgola mobile; quando implicitamente usate $.
come descrito nel precedente paragrafo, il confronto tra int(EXPR) == int($.) diventa un
problema quando $. è impostato 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 centinaia di righe, una abbreviazione per
# if ($. == 101 .. $. == 200) ...
next LINE if (1 .. /^$/); # salta le righe di intestazione, una abbreviazione per
# ... if ($. == 1 .. /^$/);
# (tipicamente in un ciclo etichettato con LINE)
s/^/> / if (/^$/ .. eof()); # quote del testo di una email
# fa il parsing dei messaggi mail
while (<>) {
$nella_intestazione = 1 .. /^$/;
$nel_corpo = /^$/ .. eof;
if ($nella_intestazione) {
# ...
} else { # nel corpo
# ...
}
} continue {
close ARGV if eof; # reimposta $. per ogni file
}
Ecco un semplice esempio per illustrare le differenze tra i due
operatori di intervallo:
@linee = (" - Pippo",
"01 - Pluto",
"1 - Paperino",
" - Topolino");
foreach (@linee) {
if (/0/ .. /1/) {
print "$_\n";
}
}
Questo programma stamperà solo le linee contenenti ``Pluto''.
Se l'operatore di intervallo viene sostituito con ... , stamperà
la linea ``Paperino''.
Ed ora alcuni semplici esempi come operatore di lista:
for (101 .. 200) { print; } # stampa $_ 100 volte
@pippo = @pippo[0 .. $#pippo]; # un "nop" [non far nulla, NdR] dispendioso
@pippo = @pippo[$#pippo-4 .. $#pippo]; # effettua uno slice degli ultimi 5 elementi
L'operatore di intervallo (in contesto di lista) fa uso dell'algoritmo magico
di auto-incremento nel caso in cui gli operandi siano stringhe. Potete affermare
@alfabeto = ('A' .. 'Z');
per ottenere tutte le normali lettere dell'alfabeto Inglese, oppure
$cifreesa = (0 .. 9, 'a' .. 'f')[$num & 15];
per ottenere una cifra esadecimale, oppure
@z2 = ('01' .. '31'); print $z2[$giornodelmese];
per ottenere le date con degli zero iniziali. Se il valore finale specificato non
è nella sequenza che viene prodotta dall'incremento magico, la sequenza
arriva fino a che il valore successivo sarebbe stato più lungo del valore finale
specificato.
Dato che ogni operando viene valutato in forma di intero, in contesto di lista 2.18 .. 3.14
restituirà due elementi.
@lista = (2.18 .. 3.14); # lo stesso che @lista = (2 .. 3);
Il ``?:'' ternario è l'operatore condizionale, proprio come in C. Funziona grossomodo come
un if-then-else [se-allora-altrimenti, NdT]. 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 che questo:
($a % 2) ? ($a += 10) : ($a += 2)
Ciò dovrebbe probabilmente essere scritto più semplicemente così:
$a += ($a % 2) ? 10 : 2;
``='' è l'usuale operatore di assegnamento.
Gli operatori di assegnamento funzionano come in C. Cioè,
$a += 2;
equivale a
$a = $a + 2;
pur senza duplicare gli effetti collaterali che la dereferenziazione dell'lvalue
potrebbe innescare, come nel caso di variabili sottoposte a 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 dell'assegnamento.
Diversamente dal C, l'operatore di assegnamento scalare produce un lvalue 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:
($temp = $globale) =~ tr [A-Z] [a-z];
Così come,
($a += 2) *= 3;
è equivalente a
$a += 2;
$a *= 3;
Analogamente, l'assegnamento di una lista in contesto di lista produce la lista degli lvalue
assegnati, e l'assegnamento di una 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 scarta il valore, poi valuta il suo argomento a destra e restituisce tale valore.
In contesto di lista, è il separatore degli argomenti di una lista, e inserisce entrambi i
suoi argomenti in una lista.
L'operatore => è un sinonimo dell'operatore virgola, ma forza qualsiasi parola
(formata interamente da caratteri) alla sua sinistra ad essere interpretata come una stringa
(dalla versione 5.001). Questo include parole che altrimenti potrebbero essere essere considerate
come una costante o una chiamata di funzione.
use constant PIPPO => "qualcosa";
my %h = ( PIPPO => 23 );
è equivalente a:
my %h = ("PIPPO", 23);
NON è:
my %h = ("qualcosa", 23);
Se l'argomento sulla sinistra non è una parola, esso viene prima interpretato come
un'espressione, e poi viene usato il suo valore come stringa.
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 );
Sul lato destro di un operatore di lista, si ha una precedenza molto bassa, in modo tale che
l'operatore controlli tutte le espressioni separate da virgola che vi 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 operatori di lista senza il bisogno di
ulteriori parentesi:
open HANDLE, "nomefile"
or die "Non posso aprire: $!\n";
Si veda anche la discussione sugli operatori di lista in Termini e Operatori di Lista (associatività a sinistra).
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 la precedenza molto bassa. Questo significa
che esso cortocircuita: cioè 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 la precedenza molto bassa. Questo lo rende
molto utile per il controllo di flusso
print FH $dati or die "Non posso scrivere su FH: $!";
Questo significa che esso cortocircuita: cioè 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 il controllo di flusso.
$a = $b or $c; # bug: questo e` sbagliato
($a = $b) or $c; # vuol dire proprio quel che si intende
$a = $b || $c; # va meglio scritto in questo modo
Tuttavia, quando si trova in un assegnamento in contesto di lista e si sta cercando di utilizzare
``||'' per il controllo di flusso, probabilmente si avrà bisogno di ``or'' in modo che l'assegnamento
assuma una precedenza più alta.
@info = stat($file) || die; # oops, stat con significato scalare
@info = stat($file) or die; # meglio, ora @info prende cio` che gli spetta
Anche stavolta, si possono sempre usare le parentesi.
( @info = stat($file) ) || die; # NdT
L'operatore binario ``xor'' restituisce l'OR-esclusivo delle due espressioni che lo circondano.
Esso non può ovviamente cortocircuitare.
Ecco le cose ha il C ma che non ha il Perl:
- & unario
-
Operatore di indirizzo. (Ma date un'occhiata all'operatore ``\'' per ottenere un riferimento).
- unario
Operatore di dereferenziazione. (I prefessi di dereferenziazione in Perl sono tipati: $, @, %,
e &).
- (TYPE)
-
Operatore di type-casting [conversione di tipo, NdR]
Mentre di solito si pensa ai quote come a dei valori letterali, in Perl funzionano come
operatori, fornendo varie tipologie di interpolazione e capacità di pattern matching.
Per queste modalità di funzionamento, Perl fornisce i consueti caratteri di quote, ma
fornisce anche una strada per scegliere carattere di quote per ciascuno di essi.
Nella seguente tabella, un {} rappresenta una coppia di delimitatori da scegliere.
Consueto Generico Significato Interpola
'' q{} Letterale no
"" qq{} Letterale si`
`` qx{} Comando si`*
qw{} Lista di parole no
// m{} Pattern match si`*
qr{} Pattern si`*
s{}{} Sostituzione si`*
tr{}{} Traslitterazione no (ma si veda sotto)
<<EOF here-doc si`*
* a meno che il delimitatore non sia ''.
I delimitatori senza graffe usano lo stesso carattere a prua e a poppa, ma i quattro tipi di
parentesi (tonde, angolari, quadrate, graffe) saranno tutti annidati, ciò significa che
q{pippo{pluto}paperino}
è lo stesso che
'pippo{pluto}paperino'
Va notato, 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 a far 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.
Di q#pippo# viene effettuato il parsing come stringa pippo , mentre q #pippo# è l'operatore
q seguito da un commento. Il suo argomento sarà preso dalla linea che segue. Questo vi
permette di scrivere:
s {pippo} # Rimpiazza pippo
{pluto} # con pluto.
Le seguenti sequenze di escape sono disponibili in costrutti che effettuano interpolazioni e nelle
traslitterazioni.
\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 carattere ottale (ESC)
\x1b carattere esadecimale (ESC)
\x{263a} carattere esadec. esteso (SMILEY)
\c[ carattere di controllo (ESC)
\N{nome} carattere Unicode nominale
NOTA: 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 minuscolo
\u rende il carattere successivo maiuscolo
\L rende minuscolo fino a \E
\U rende maiuscolo fino \E
\E termina la modifica del case
\Q quota i metacaratteri fino a \E
Se state usando use locale , la mappatura di maiuscole/minuscole usata da \l , \L , \u e \U
viene presa dalle impostazioni linguistiche correnti. Si veda perllocale.
Se è stato usato Unicode (per esempio, \N{} o caratteri esadecimali più grandi
di 0x100), la mappatura di maiuscole/minuscole usata da \l , \L , \u e \U segue la definizione
dello standard Unicode. Per la documentazione di \N{name} , si veda charnames.
Tutti i sistemi utilizzano "\n" per rappresentare un terminatore di linea, chiamato ``newline''
[letteralmente ``nuova linea'', NdT]. Non esiste qualcosa come un invariante, un 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 non emettere dati reali. In generale, usate "\n" quando
intendete un ``newline'' per il vostro sistema, ma usate un ASCII letterale 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, un giorno o l'altro potreste prendervi una scottatura.
Per costrutti che interpolano, le variabili che iniziano con ``$ '' o ``@ '' verranno interpolate.
Variabili come $a[3] oppure $href->{key}[0] verranno anch'esse interpolate,
così come gli slice [fette, NdT] di array e hash. Ma non le chiamate ad un metodo come
$oggetto->metodo .
Interpolare un array o uno slice, interpola gli elementi nell'ordine, separati dal valore di $" ;
il che è equivalente ad interpolare join $", @array . Gli array ``Punctuation'' [array il
cui nome è costituito da segni di punteggiatura, NdT] come @+ sono interpolati solamente
se il nome è racchiuso tra parentesi @{+} .
Non è possibile includere un letterale come $ o @ all'interno di una sequenza \Q .
Un $ o @ senza escape [non preceduti da \, NdT] interpolano la variabile corrispondente,
mentre facendo precedere la sequenza da un \ causerà l'inserimento della stringa
letterale \$ . Dovrete 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 possa essere incorporata nel pattern, dalle
variabili. Se non è questo che volete, usate \Q per interpolare una variabile
in maniera letterale.
A parte il comportamento sopra descritto, Perl non espande più livelli di interpolazione.
In particolare, contrariamente alle aspettative dei programmatori shell, il back-quote
[l'uso dei due backtick, ovvero gli apici inversi: ` qualcosa `, NdR] NON interpola all'interno di
un doppio quote [l'uso delle virgolette doppie: `` qualcosa '', NdR], né tantomeno i quote singoli
[virgolette ', NdR] impediscono la valutazione delle variabili se utilizzate all'interno di un
doppio quote.
Ecco gli operatori a-la quote che si applicano al pattern matching e ad attività correlate.
- ?PATTERN?
-
Questo è come la ricerca con
/pattern/ , eccetto che trova una corrispondenza solo per una
volta fra chiamate all'operatore reset(). Per esempio, rappresenta una utile ottimizzazione quando si
vuole visualizzare solo la prima occorrenza di qualcosa in ogni file di un insieme di file.
Con reset() vengono reimpostati solo i pattern ?? locali al package corrente.
while (<>) {
if (?^$?) {
# linea vuota tra intestazione e corpo
}
} continue {
reset if eof; # pulisce lo stato di ?? per il prossimo file
}
Questo utilizzo è vagamente deprecato, il che significa che potrebbe forse essere
rimosso in qualche versione di Perl nel lontano futuro, forse da qualche parte intorno all'anno
2168.
- m/PATTERN/cgimosx
-
- /PATTERN/cgimosx
-
Cerca una stringa per un pattern match, e in un contesto scalare restituisce vero se la
corrispondenza viene trovata, falso altrimenti. Se non viene specificata alcuna stringa
attraverso l'operatore
=~ o !~ , la ricerca della stringa avviene in $_.
(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
va ricordato che =~ ha una precedenza molto alta). Si veda anche perlre.
Si veda perllocale per ulteriori considerazioni da applicare quando è in uso
use locale .
Le opzioni sono:
c Non reimposta la posizione di ricerca in seguito ad un match fallito quando si sta utilizzando /g .
g Fa un match globale, cioe` trova tutte le occorrenze.
i Esegue un pattern match senza preoccuparsi di maiuscole o minuscole.
m Tratta le stringhe come linee multiple.
o Compila il pattern solo una volta.
s Tratta la stringa come una singola linea.
x Usa le espressioni regolari estese.
Se il delimitatore è ``/'', allora la m iniziale è opzionale. Con m potete
usare una coppia di caratteri non alfanumerici, 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
inclinato, NdT]. Se il delimitatore è ``?'', allora si applica la regola del
match-solo-per-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
ricompilato) ogni volta che viene valutato il pattern di ricerca, tranne
quando il delimitatore è un quote singolo [ ' , NdR]. (Va notato che $( , $) ,
e $| non sono interpolati perché assomigliano a dei test di fine stringa). Se volete
che tali pattern siano compilati solo una volta, aggiungete un /o dopo il delimitatore finale.
Questo evita costose ricompilazioni a tempo di esecuzione, ed è utile quando il valore
che state interpolando non cambierà durante il tempo di vita del programma. Comunque,
menzionare /o costituisce una promessa a non cambiare le variabili nel pattern.
Se le cambiate, Perl non ve lo notificherà. Si veda anche qr/STRINGA/imosx.
Se PATTERN restituisce la stringa vuota, verrà utilizzata l'ultima espressione regolare
valutata con successo. In questo caso, sul pattern vuoto avranno effetto solo i flag g e
c - gli altri flag vengono presi dal pattern originale. Se in precedenza non è avvenuto
alcun match, ciò agirà (silenziosamente) come un vero e proprio pattern vuoto
(che farà sempre match).
Se non viene utilizzata l'opzione /g , m// in contesto di lista restituisce una lista che
consiste di sottoespressioni che hanno fatto match con le parentesi nel pattern, cioè,
($1 , $2 , $3 ...). (Va notato che qui $1 ecc. vengono anche impostati, e che ciò
è diverso dal comportamento che si aveva in Perl 4). Quando non ci sono parentesi nel
pattern, il valore restituito per indicare il successo è la lista (1) . Con o senza
parentesi, a seguito di un insuccesso viene restituita una lista vuota.
Esempi:
open(TTY, '/dev/tty');
<TTY> =~ /^y/i && pippo(); # esegue pippo se lo si desidera
if (/Versione: *([0-9.]*)/) { $versione = $1; }
next if m#^/usr/spool/uucp#;
# il grep dei poveri
$arg = shift;
while (<>) {
print if /$arg/o; # compila solo una volta
}
if (($F1, $F2, $Ecc) = ($pippo =~ /^(\S+)\s+(\S+)\s*(.*)/))
L'ultimo esempio divide $pippo nelle prime due parole e in ciò che rimane della linea, ed
assegna questi tre campi a $F1, $F2, ed $Ecc. La condizione è vera se qualsiasi delle
variabili viene assegnata, cioè, se al pattern è corrisposto un 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 di
lista, restituisce una lista delle sottostringhe a cui è corrisposto un match, come se ci fossero
parentesi intorno all'intero pattern.
In contesto scalare, ciascuna esecuzione di m//g trova il match successivo, restituendo vero se
ha effettuato il match, e falso se non ci sono ulteriori match. La posizione dopo l'ultimo match
può esser letta o impostata utilizzando la funzione pos(); si veda perlfunc/pos.
Un match che fallisce, di norma reimposta la posizione di ricerca all'inizio della
stringa, ma lo si può evitare con l'aggiunta del modificatore /c (ad es. m//gc ).
Se la stringa alla quale si applica il match viene modificata, la posizione di ricerca sarà
reimpostata.
Potete mescolare il match m//g con m/\G.../g , dove \G è un'asserzione zero-width
[di ampiezza zero, NdT] che effettua il match all'esatta posizione dove l'eventuale precedente
m//g si era interrotto. Senza il moficiatore /g , l'asserzione \G si ancora ancora a pos(),
ma il match viene ovviamente tentato solo una volta. Usare \G senza /g su una
stringa sulla quale non è stato applicato un match di tipo /g , equivale ad un'asserzione
\A che effettua il match dell'inzio della stringa. Va notato anche che, al momento, \G
è adeguatamente supportato solo quando è ancorato all'inzio del pattern.
Esempi:
# contesto di lista
($uno,$cinque,$quindici) = (`uptime` =~ /(\d+\.\d+)/g);
# contesto scalare
$/ = "";
while (defined($capoverso = <>)) {
while ($capoverso =~ /[a-z]['")]*[.!?]+['")]*\s/g) {
$frasi++;
}
}
print "$frasi\n";
# utilizzo di m//gc con \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 "Finale: '$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
Finale: 'q', pos=8
Si noti che l'ultimo match ha effettuato il match di q invece di p , la stessa cosa che
avrebbe fatto un match senza l'ancora \G . Si noti anche che l'ultimo match non ha aggiornato
pos -- pos viene aggiornato solamente su un match con /g . Se il match finale ha davvero
effettuato il match di p , ci sarebbe da scommettere che si sta utillizzando un Perl più
vecchio (pre-5.6.0).
Un idioma utile per gli scanner sul genere di lex , è /\G.../gc .
È possibile combinare diverse espressioni regolari come questa per elaborare una stringa
pezzo per pezzo, eseguendo diverse azioni a seconda dell'espressione regolare corrispondente.
Ogni espressione regolare cerca di effettuare il match da dove ha terminato la precedente.
$_ = <<'EOL';
$url = new URI::URL "http://www/"; die if $url eq "xXx";
EOL
LOOP:
{
print(" cifre"), redo LOOP if /\G\d+\b[,.;]?\s*/gc;
print(" minuscolo"), redo LOOP if /\G[a-z]+\b[,.;]?\s*/gc;
print(" MAISUCOLO"), redo LOOP if /\G[A-Z]+\b[,.;]?\s*/gc;
print(" Primo carattere maiuscolo"), redo LOOP if /\G[A-Z][a-z]+\b[,.;]?\s*/gc;
print(" MiStO"), redo LOOP if /\G[A-Za-z]+\b[,.;]?\s*/gc;
print(" alfanumerico"), redo LOOP if /\G[A-Za-z0-9]+\b[,.;]?\s*/gc;
print(" rumore di linea"), redo LOOP if /\G[^A-Za-z0-9]+/gc;
print ". E` tutto!\n";
}
Ecco qui l'output (diviso su diverse linee):
rumore di linea minuscolo rumore di linea minuscolo MAISUCOLO rumore di linea
MAISUCOLO rumore di linea minuscolo rumore di linea minuscolo rumore di linea
minuscolo minuscolo rumore di linea minuscolo minuscolo rumore di linea
MiStO rumore di linea. E` tutto!
- q/STRINGA/
-
'STRINGA'
-
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.
$pippo = q!Ho detto, "Tu dici, 'Lei lo dice.'"!;
$pluto = q('Questo e`.');
$paperino = '\n'; # una stringa di due caratteri
- qq/STRINGA/
-
- ``STRINGA''
-
Un doppio quote, stringa interpolata.
$_ .= qq
(*** La riga precedente contiene l'indecente parola "$1".\n)
if /\b(tcl|java|python)\b/i; # :-)
$paperino = "\n"; # una stringa di un carattere
- qr/STRINGA/imosx
-
Questo operatore quota (e possibilmente compila) la sua STRINGA come una espressione regolare.
STRINGA viene interpolata allo stesso modo di PATTERN in
m/PATTERN/ . Se come
delimitatore viene usato ``''', l'interpolazione non viene fatta. Restituisce un valore Perl che
può essere usato al posto della corrispondente espressione /STRINGA/imosx .
Per esempio,
$rex = qr/mia.STRINGA/is;
s/$rex/pippo/;
è equivalente a
s/mia.STRINGA/pippo/is;
Il risultato può esser utilizzato come un sotto-pattern in un match:
$re = qr/$pattern/;
$stringa =~ /pippo${re}pluto/; # puo` esser interpolato in altri pattern
$stringa =~ $re; # oppure usato da solo
$stringa =~ /$re/; # o in questo modo
Dato che Perl può compilare il pattern al momento dell'esecuzione dell'operatore qr(),
in alcune situazioni utilizzare qr() potrebbe portare a dei vantaggi in termini di
velocità, specialmente se il risultato di qr() viene utilizzato da solo:
sub match {
my $patterns = shift;
my @compilato = map qr/$_/i, @$patterns;
grep {
my $successo = 0;
foreach my $pat (@compilato) {
$successo = 1, last if /$pat/;
}
$successo;
} @_;
}
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 predecendete se
non avessimo usato l'operatore qr()).
Le opzioni sono:
i Effettua un pattern matching senza badare a minuscole/maiuscole.
m Tratta la stringa come fosse su piu` linee.
o Compila il pattern una volta sola.
s Tratta la stringa come fosse una singola linea.
x Utilizza le espressioni regolari estese.
Si veda perlre per delle informazioni aggiuntive sulla sintassi valida per STRINGA, e per uno sguardo
dettagliato alla semantica delle espressioni regolari.
- qx/STRINGA/
-
- `STRINGA`
-
Una stringa che viene (forse) interpolata e poi eseguita come un comando di sistema con
/bin/sh o equivalente. Sarà rispettato l'utilizzo dei caratteri jolly della shell
[le wildcard * ? ecc, NdR], pipe e redirezioni. L'output raccolto viene restituito; lo standard error
no. In contesto scalare, se il comando fallisce viene restituita come singola stringa (potenzialmente
multilinea), oppure undef. In contesto di lista, se il comando fallisce restituisce una lista di linee
(o comunque in base a come è stato definito $/ o $INPUT_RECORD_SEPARATOR), o una lista vuota .
Dato che il backtick non influisce sullo standard error, se interessa risolvere tale questione va usata
la sintassi di shell per il descrittore di file (supponendo che la shell la supporti).
Per catturare assieme lo STDERR e STDOUT di un comando:
$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 al fine di catturare lo STDERR ma lasciare che lo
STDOUT termini nel vecchio STDERR:
$output = `cmd 3>&1 1>&2 2>&3 3>&-`;
Per leggere separatamente sia lo STDOUT che lo STDERR di un comando, è più facile
redirezionarli separatamente a dei file, e poi leggere da questi file quando il programma è
terminato:
system("programma argomenti 1>programma.stdout 2>programma.stderr");
Utilizzare un quote singolo come delimitatore protegge il comando dall'interpolazione a doppio
quote di Perl, passandolo invece in una shell:
$perl_info = qx(ps $$); # $$
$shell_info = qx'ps $$'; # che e` il $$ della nuova shell
Come quella stringa venga valutata è un 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 in che modo si debba fare l'escape di tali caratteri. Si veda perlsec
per un esempio pulito e sicuro di fork() ed exec() manuali per emulare in sicurezza il backtick.
Su alcune piattaforme (specialmente quelle tipo DOS), la shell potrebbe non esser capace di
trattare con comandi multi linea, quindi inserire dei newline nella stringa potrebbe non darvi
quello che vi aspettate. Se la vostra shell lo supporta potete valutare comandi multipli in una linea
singola separandoli con il carattere separatore di comando (ad es. ; sulla maggior parte
delle shell Unix; & sulla shell cmd di Windows NT).
A partire dalla v5.6.0, Perl cercerà di terminare le operazioni di I/O in corso di tutti i file
aperti prima di iniziare il processo figlio, ma questo potrebbe non essere supportato su alcune
piattaforme (si veda perlport). Per esserne sicuri, potreste aver bisogno di impostare $|
($AUTOFLUSH con il modulo English) o chiamare il metodo autoslush() di IO::Handle su ogni
handle aperto.
Fate attenzione al fatto che alcuni comandi di shell potrebbero porre delle restrizioni sulla
lunghezza della linea di comando. Dovete assicurarvi che le vostre stringhe non eccedano questo
limite dopo le necessarie interpolazioni. Per ulteriori dettagli riguardo al vostro ambiente si vedano
le note di rilascio relative alla specifica piattaforma utilizzata.
Usare questo operatore può portare a programmi il cui porting [migrazione tra diversi
ambienti, NdR] è difficile, dato che i comandi di shell chiamati variano tra i vari sistemi, e
potrebbero di fatto non essere affatto presenti. Come esempio, il comando type nelle shell POSIX
è molto differente dal comando type del DOS. Ciò non significa che dovreste uscire
dal vostro modo di operare per aggirare i backtick quando sono la strada giusta per ottenere il
risultato. Perl fu fatto per essere un linguaggio ``glue'' [collante, NdT], e una delle cose che Perl
incolla assieme sono i comandi. Dovete solo capire cova volete ottenere.
Per ulteriori discussioni si veda Operatori di I/O.
- qw/STRINGA/
-
Valuta una lista delle parole estratta dalla STRINGA, utilizzando uno spazio incorporato come
delimitatore di parole. Può essere grossomodo inteso come equivalente a:
split(' ', q/STRINGA/);
la differenza sta nel fatto che esso genera una vera lista a tempo di compilazione, e in
contesto scalare restituisce l'ultimo elemento della lista. Quindi questa espressione:
qw( pippo pluto paperino )
è semanticamente equivalente alla lista:
'pippo', 'pluto', 'paperino'
Alcuni esempi che si osservano di frequente:
use POSIX qw( setlocale localeconv )
@EXPORT = qw( pippo pluto paperino );
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 il parametro
-w (cioè, la variabile $^W ) produce degli avvertimenti se la STRINGA contiene ``,'' o
il carattere ``#''.
- s/PATTERN/SOSTITUZIONE/egimosx
-
Cerca una stringa in base ad un pattern, e se la trova, sostituisce quel pattern con il testo di
sostituzione e restituisce il numero di sostituzioni fatte. Altrimenti restituisce falso (in
particolare, la stringa vuota).
Se non viene specificata alcuna stringa tramite l'operatore =~ o !~ , la ricerca e la modifica
viene effettuata sulla variabile $_ . (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, cioè, un lvalue).
Se il delimitatore scelto è un quote singolo, non viene fatta interpolazione né
su PATTERN né su SOSTITUZIONE. In caso contrario, se il PATTERN contiene un $ che assomiglia ad
una variabile anziché al test di fine stringa, la variabile sarà interpolata nel
pattern a tempo di esecuzione. Se volete che il pattern venga compilato solo la prima volta che la
variabile viene interpolata, usate l'opzione /o . Se il pattern valuta una stringa vuota,
verrà utilizzata l'ultima espressione regolare eseguita con successo. Per ulteriori spiegazioni
su questo argomento si veda perlre. Per discussioni su considerazioni aggiuntive che si applicano
quando è in uso use locale , si veda perllocale.
Le opzioni sono:
e Valuta il lato destro di un'espressione.
g Rimpiazza globalmente, cioe`, tutte le occorrenze.
i Esegue un pattern matching senza badare a minuscole/maiuscole.
m Tratta la stringa come fosse su linee multiple.
o Compila il pattern solo una volta.
s Tratta la stringa come fosse una singola linea.
x Usa espressioni regolari estese.
Qualsiasi delimitatore non-alfanumerico, o che non sia uno spazio, potrebbe rimpiazzare gli slash.
Se viene utilizzato un singolo quote, non viene fatta un'interpretazione sulla stringa di
sostituzione (ad ogni modo il modificatore /e sovrascrive questo comportamento). Diversamente
da Perl 4, Perl 5 tratta i backtick come dei normali delimitatori; il testo di sostituzione non
viene valutato come un comando. Se il PATTERN è delimitato da quote con parentesi, la
SOSTITUZIONE ha la sua personale coppia di quote, che potrebbe o meno essere una coppia di
parentesi, ad esempio, s(pippo)(pluto) oppure s<pippo>/pluto/ . Un /e farà
sì che la porzione di sostituzione venga trattata come una vera e propria espressione Perl e
valutata immediatamente. Ad ogni modo, la sintassi viene controllata a tempo di
compilazione. Un secondo modificatore e causerà un eval sulla porzione di sostituzione
prima di essere eseguita come espressione Perl.
Esempi:
s/\bverdi\b/malva/g; # non cambia le [piante, NdR] sempreverdi
$path =~ s|/usr/bin|/usr/local/bin|;
s/Login: $pippo/Login: $pluto/; # pattern a tempo di esecuzione
($pippo = $pluto) =~ s/questo/quello/; # prima copia, poi cambia
$contatore = ($paragrafo =~ s/Mister\b/Mr./g); # conta le sostituzioni effettuate
$_ = 'abc123xyz';
s/\d+/$&*2/e; # produce 'abc246xyz'
s/\d+/sprintf("%5d",$&)/e; # produce 'abc 246xyz'
s/\w/$& x 2/eg; # produce 'aabbcc 224466xxyyzz'
s/%(.)/$percentuale{$1}/g; # cambia la percentuale di escape; niente /e
s/%(.)/$percentuale{$1} || $&/ge; # ora un'espressione, dunque /e
s/^=(\w+)/&pod($1)/ge; # utilizza una chiamata di funzione
# espande le variabili in $_, ma solo dinamicamente, usando
# la dereferenziazione simbolica
s/\$(\w+)/${$1}/g;
# Aggiunge uno al valore di ogni numero della stringa
s/(\d+)/1 + $1/eg;
# Espande ogni variabile scalare
# (inclusi i lessicali) in $_ : Prima $1 viene interpolato
# nel nome della variabile, e poi valutato
s/(\$\w+)/$1/eeg;
# Cancella i commenti C (la maggior parte)
$programma =~ s {
/\* # Effettua il match del delimitatore iniziale.
.*? # Effettua il match del minimo numero di caratteri.
\*/ # Effettua il match del delimitatore piu` prossimo.
} []gsx;
s/^\s*(.*?)\s*$/$1/; # elimina gli spazi vuoti in $_, in maniera computazionalmente dispendiosa
for ($variabile) { # elimina gli spazi vuoti in $_, in maniera computazionalmente conveniente
s/^\s+//;
s/\s+$//;
}
s/([^ ]*) *([^ ]*)/$2 $1/; # inverte i primi due campi
Va notato l'utilizzo di $ invece di \ nell'ultimo esempio. Diversamente da sed, si usa
\cifra solamente nella parte sinistra. Altrove è $<cifra>.
A volte, non si può usare un solo /g per ottenere tutti i cambi che si possono
desiderare. Ecco due esempi comuni:
# mette le virgole nei posti giusti in un numero intero
1 while s/(\d)(\d\d\d)(?!\d)/$1,$2/g;
# espande i tab ad una spaziatura di 8 colonne
1 while s/\t+/' ' x (length($&)*8 - length($`)%8)/e;
- tr/LISTADIRICERCA/SOSTITUZIONE/cds
-
- y/LISTADIRICERCA/LISTADISOSTITUZIONE/cds
Traslittera tutte le occorrenze dei caratteri trovati nella lista di ricerca con i corrispondenti
caratteri nella lista di sostituzione. Restituisce il numero di caratteri sostituiti o
cancellati. Se non si specifica 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, cioè, un lvalue).
-
Un insieme di caratteri può essere specificato tramite un hyphen [trattino - , NdT],
quindi
tr/A-J/0-9/ effettua la stessa sostituzione di tr/ACEGIBDFHJ/0246813579/ . Per i
devoti di sed, è possibile usare y come sinonimo di tr . Se la LISTADIRICERCA
è delimitata da quote con parentesi, la LISTADISOSTITUZIONE avrà la sua
propria coppia di quote, che potrebbe o meno essere delle parentesi, ovvero tr[A-Z][a-z] o
tr(+\-*/)/ABCD/ .
Va notato che tr non crea classi di caratteri di espressioni regolari come fanno \d o
[:lower:] . L'operatore tr non è equivalente all'utility tr(1). Se si desidera
effettuare il mapping tra stringhe maiuscole/minuscole, si vedano perlfunc/lc e
perlfunc/uc, ed in generale si consideri l'utilizzo dell'operatore s se si ha bisogno
delle espressioni regolari.
Va notato anche che l'idea di un'intera gamma 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. Un sano principio È quello di utilizzare degli intervalli di
caratteri che iniziano e finiscono alfabeticamemente con lo stesso case (minuscolo: a-e,
maiuscolo: A-E), oppure cifre (0-4). Tutto il resto è poco sicuro. Nel dubbio,
va precisato interamente tutto il set di caratteri.
Opzioni:
c Inverte la LISTADIRICERCA.
d Cancella i caratteri trovati ma non sostituiti.
s Riduce i caratteri sostituiti duplicati.
Se si specifica il modificatore /c , il set di caratteri della LISTADIRICERCA viene
invertito. Se viene specificato il modificatore /d , viene cancellato qualsiasi carattere
specificato nella LISTADIRICERCA non trovato nella LISTADISOSTITUZIONE. (Va notato che
questo è leggermente più flessibile rispetto al comportamento di alcuni programmi tr,
i quali eliminano qualsiasi cosa essi trovino nella LISTADIRICERCA). Se viene specificato il modificatore
/s , le sequenze di caratteri che sono state traslitterate nello stesso carattere,
vengono ridotte ad una singola istanza di quel carattere.
Se viene usato il modificatore /d , la LISTADISOSTITUZIONE viene interpretata proprio come
specificato. Altrimenti, se la LISTADISOSTITUZIONE è più breve della LISTADIRICERCA,
il carattere finale viene replicato fino alla sufficiente lunghezza. Se la LISTADISOSTITUZIONE è
vuota, la LISTADIRICERCA viene replicata. Quest'ultima cosa è utile per contare i caratteri
in una classe o per ridurre sequenze di caratteri in una classe.
Esempi:
$ARGV[1] =~ tr/A-Z/a-z/; # trasforma tutto in minuscolo
$cnt = tr/*/*/; # conta gli asterischi in $_
$cnt = $cielo =~ tr/*/*/; # conta gli asterischi nel $cielo [asterisco in inglese e` 'star' che significa anche stella, NdR]
$cnt = tr/0-9//; # conta i numeri in $_
tr/a-zA-Z//s; # commercialista -> comercialista
($HOST = $host) =~ tr/a-z/A-Z/;
tr/a-zA-Z/ /cs; # trasforma i caratteri non alfabetici in spazi
tr [\200-\377]
[\000-\177]; # cancella l'ottavo bit
Se vengono date più traslitterazioni per un carattere, viene utilizzata solo la prima:
tr/AAA/XYZ/
traslittera qualunque A con una X.
Dato che la tabella di traslitterazione viene costruita a tempo di compilazione, né la
LISTADIRICERCA, né la LISTADISOSTITUZIONE sono soggette ad interpolazione con il
doppio quote. Il che vuol dire che se volete usare una variabile, dovete usare un 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'' [documento immediato, NdR]. A seguito di un
<< si specifica una stringa che
termina il materiale quotato, e tutte le linee che seguono quella corrente fino alla stringa di
terminazione costituiscono il valore di quell'elemento. La stringa di terminazione potrebbe essere sia un
identificatore (una parola), o del testo quotato. Se quotato, il tipo di quote che si usa
determina il trattamento del testo, come nel normale quote. Un identificatore non quotato
funziona come un quote doppio. Se l'identificatore non è quotato, non ci devono essere spazi
tra << e l'identificatore. (Se mettete uno spazio, sarà trattato come
identificatore nullo, che è valido, il cui match avviene con la prima linea vuota).
La stringa di terminazione deve esser presente (non quotata e non circondata da spazi) sulla linea di
terminazione.
print <<EOF;
Il prezzo e` $Prezzo.
EOF
print << "EOF"; # lo stesso come sopra
Il prezzo e` $Prezzo.
EOF
print << `EOC`; # esegue i comandi
echo alto
echo basso
EOC
print <<"pippo", <<"pluto"; # potete accatastarli
Ho detto pippo.
pippo
Ho detto pluto.
pluto
miafunz(<< "QUESTO", 23, <<'QUELLO');
Qui c'e` una linea
o due.
QUESTO
e qui un'altra.
QUELLO
Non si dimentichi che va messo un punto e virgola alla fine dell'istruzione, Perl non sa
che non si sta cercando di fare questo:
print <<ABC
179231
ABC
+ 20;
Se si vuole che la propria sintassi here-doc venga indentata con il resto del codice, dovrete
rimuovere manualmente lo spazio iniziale da ciascuna linea:
($quote = <<'FINE') =~ s/^\s+//gm;
La strada prosegue senza sosta,
giu` dalla porta dove e` iniziata.
FINE
Se si usano here-doc all'interno di un costrutto delimitato, come in s///eg , il materiale quotato
deve andare tutto all'interno del delimitatore finale.
Quindi invece di
s/questo/<<E . 'quello'
altro
E
. 'piu '/eg;
dovete scrivere
s/questo/<<E . 'quello'
. 'piu'/eg;
altro
E
Se l'identificatore terminatore si trova sull'ultima linea del programma, dovete assicurarvi che dopo
l'identificatore ci sia ``un a capo''; altrimenti, Perl vi darà un avvertimento
Can't find string terminator ``END'' anywhere before EOF... [Non riesco a trovare il terminatore di
stringa ``END'' prima della fine del file..., NdR].
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 è per fare il backslash del carattere di quote:
print << "abc\"def";
sto testando...
abc"def
Per finire, le stringhe quotate non possono estendersi su più righe. La regola generale
è che l'identificatore deve essere una stringa letterale. Ci si attenga a ciò e si dovrebbe
essere al sicuro.
Quando viene presentato con qualcosa che potrebbe avere svariate
interpretazioni, Perl utilizza il principio DWIM (che è ``Do What I Mean'')
[Fa quello che intendo, NdT] per scegliere l'interpretazione più
probabile. Questa strategia ha così tanto successo che spesso i programmatori Perl
non sospettano nulla riguardo all'ambivalenza di cià che scrivono. Ma da un momento
all'altro, le idee del Perl differiscono in modo sostanziale da quello che voleva dire in tutta
onestà l'autore.
Questa sezione si auspica di chiarire come Perl gestisce i costrutti quotati. Sebbene la ragione
più comune per imparare ciò è il districarsi nel labirinto delle espressioni
regolari, dato che i passi iniziali del parsing sono gli stessi di quelli degli operatori di
quoting, vengono discussi tutti assieme.
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 si capisce questa regola, si potrebbe saltare il resto della sezione ad una prima
lettura. Le altre regole sono suscettibili di contraddire le aspettative dell'utente molto meno
frequentemente della prima regola.
Alcuni passi, discussi in seguito, vengono eseguiti contemporanemanete, ma dato che i loro risultati
sono gli stessi, si considerano individualmente. Per costrutti di quoting differenti, Perl esegue
un differente numero di passi, da uno a cinque, ma questi passi sono eseguiti sempre nello stesso
ordine.
- Trovare la fine
-
Il primo passo è trovare la fine del costrutto quotato, sia si tratti di un delimitatore
multicarattere
"\nEOF\n" nel costrutto <<EOF , sia che si tratti di un / che termina un
costrutto qq// , un ] che termina un qq[] , o un > che termina un fileglob che inizia con
< .
Quando viene cercato un delimitatori a singolo carattere non simmetrico, come / , vengono omesse
le combinazioni di \\ e \/ . Comunque, quando si cerca un delimitatore a singolo carattere
simmetrico come [ , le combinazioni di \\ , \] , e \[ sono tutte trascurate, e
i [ , ] nidificati vengono anch'essi trascurati. Quando si cercano delimitatori multicarattere,
non viene trascurato nulla.
Per costrutti con delimitatori formati da 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{"$pippo/$pluto"}"
o:
m/
pluto # NON e` 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 uno SPAZIO ,
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\/ viene interpretato come una parte di \/ ,
e il seguente / non viene riconosciuto come delimitatore.
Invece, si usino \034 o \x1c alla fine dei costrutti quotati.
- Rimozione del backslash prima dei delimitatori
-
Durante il secondo passo, il testo tra il delimitatore iniziale
e finale viene copiato in una locazione sicura, il
\ viene rimosso
dalle combinazioni che consistono di \ e il delimitatore - o i delimitatori, cioè
entrambi i delimitatori di inizio e di fine devono essere differenti.
Questa rimozione non accade per i delimitatori multicarattere.
Va notato che la combinazione \\ viene lasciata intatta così come è stata trovata.
A partire da questa fase, 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///
-
Non viene effettuata alcuna interpolazione.
'' , 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 corrispondente costrutto Perl. Quindi, "$pippo\Qpaperino$pluto"
viene convertito internamente in $pippo . (quotemeta("paperino" . $pluto)) .
Le altre combinazioni sono rimpiazzate con espansioni appropriate.
Va sottolineato che qualsiasi cosa tra \Q e \E
viene interpolata alla stessa maniera. Qualcosa come "\Q\\E" non ha alcun
\E al suo interno. Invece, ha \Q , \\ , e E , cosà che
il risultato sia lo stesso che per "\\\\E" . Come regola generale, i backslash tra \Q
e \E potrebbero portare a risultati controintuitivi. Cosà,
"\Q\t\E" viene convertito in quotemeta("\t") , il quale è lo stesso
che "\\\t" (dato che TAB non è alfanumerico). Va anche notato che:
$str = '\t';
return "\Q$str";
può essere più vicina alla probabile intenzione di chi ha scrtto "\Q\t\E" .
Scalari interpolati e array vengono convertiti internamente con gli
operatori di concatenazione join e . . Quindi, "$pippo XXX '@arr'"
diventa:
$pippo . " XXX '" . (join $", @arr) . "'";
Tutte le operazioni qui sopra vengono effettuate simultaneamente, da sinistra a destra.
Dato che il risultato di "\Q STRINGA \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 per diventare "\\\$" ; se non è
così, viene interpretato come l'inizio di uno scalare interpolato.
Va anche notato che il codice di interpolazione ha bisogno di prendere una
decisione su dove finisca lo scalare interpolato. Per esempio, sia
"a $b -> {c}" significa effettivamente:
"a " . $b . " -> {c}";
oppure:
"a " . $b -> {c};
Il più delle volte, il testo più lungo possibile che non
include degli spazi tra i componenti e che contiene parentesi graffe o quadre corrispondenti.
Poiché l'esito potrebbe essere determinato in base
ad una analisi di stime euristiche, il risultato non è
prevedibile a priori. Fortunatamente, di solito va bene nei casi ambigui.
?RE? , /RE/ , m/RE/ , s/RE/pippo/ ,
-
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 delle espressioni regolari (incluso \ ) non viene
eseguita. Inoltre, dentro un (?{BLOCCO}) , (?# commento ) , e
un commento # in una espressione regolare con //x , non viene eseguita
alcuna elaborazione. Questo è il primo passo nel quale è rilevante la presenza
del modificatore //x .
L'interpolazione ha diverse stranezze: $| , $( , e $) non vengono
interpolati, e i costrutti $var[QUALCOSA] sono votati (da disparati diversi stimatori) ad essere
o un elemento di un array o un $var seguito da una espressione regolare alternativa.
Questo è il caso nel quale la notazione ${arr[$pluto]}
è particolarmente utile: /${arr[0-9]}/ è interpretata come l'elemento
dell'array -9 , non come un'espressione regolare dalla variabile
$arr seguita da una cifra, che sarebbe l'interpretazione di /$arr[0-9]/ .
Dato che si possono verificare votazioni tra differenti stimatori, il risultato
non è predicibile.
È a questo punto che \1 viene convertito a malincuore in $1
nel testo di sostituzione di s/// per correggere gli incorregibili
sed hacker che non hanno ancora trovato la giusta espressione idiomatica. Viene emesso un
avvertimento se sulla linea di comando sono stati impostati la direttiva use warnings o il flag
-w (cioè, la variabile $^W ).
La mancanza di elaborazione di \\ crea delle specifiche restrizioni
sul testo post-processato. Se il delimitatore è / , nel risulato di questo passo non
si può avere la combinazione \/ . / terminer&agreve;
l'espressione regolare, \/ sarà ripulita da / nel passo precedente,
e \\/ verrà lasciato così com'è. Dato che dentro ad un'espressione
regolare / è equivalente a \/ , ciò non ha importanza a meno che il
delimitatore non sia un carattere speciale per il motore delle espressioni regolari, come in
s*pippo*pluto* , m[pippo] , o ?pippo? ; oppure un carattere alfanumerico, come in:
m m ^ a \s* b mmx;
Nell'espressione regolare qui 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 un motivo per il quale siamo incoraggiati a restringere
i delimitatori a scelte non alfanumeriche e senza spazi vuoti.
Questo passo è l'ultimo per tutti i costrutti tranne che per 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, se opportuno, potrebbe essere ottimizzato
per esser calcolato a tempo di compilazione. Dopo la pre-elaborazione
descritta sopra, e possibilmente dopo la valutazione nel caso siano coinvolti concatenazione, unione,
traduzione dei case [delimitatori, NdT], o il mataquoting, la stringa risultante
viene passata per la compilazione al motore delle espressioni regolari.
Qualunque cosa accada nel motore delle espressioni regolari, potrebbe essere discusso meglio in
perlre, ma per ragioni di continuità, dobbiamo farlo anche qui.
Questo è un altro passo nel quale è rilevante la presenza del modificatore //x .
Il motore delle espressioni regolari scansiona la stringa da sinistra a destra e la converte in un
automa a stati finiti.
I caratteri con backslash sono o rimpiazzati con le corrispondenti stringhe letterali
(come con \{ ), oppure generano dei nodi speciali nell'automa a stati finiti (come con \b ).
I caratteri speciali per il motore delle espressioni regolari (come | ) generano i nodi
corrispondenti o gruppi di nodi. I commenti come (?#...) vengono ignorati. Tutto il resto viene o
convertito in delle stringhe letterali di cui effettuare il match, o altrimenti viene
ignorato (come avviene per lo spazio vuoto e i commenti stile # se è presente //x ).
Il parsing del costrutto della classe di caratteri tra parentesi quadre, [...] , è
piuttosto differente rispetto alla regola utilizzata per il resto del pattern.
Il terminatore di questo costrutto viene trovato utilizzando le stesse
regole usate per trovare il terminatore di un costrutto delimitato da {} ,
l'unica eccezione è che ] immediatamente seguito da [
viene trattato come se fosse preceduto da un backslash. Analogamente, il terminatore
(?{...}) viene trovato usando le stesse regole usate per trovare il terminatore
di un costrutto delimitato da {} .
È possibile ispezionare sia la stringa data al motore delle espressioni regolari che
l'automa a stati finiti risultante. Si vedano gli argomenti debug /debugcolor
nella direttiva use re , così come per il parametro -Dr sulla
linea di comando di Perl in perlrun/``Parametri su linea di comando''.
- Ottimizzazioni delle espressioni regolari
-
Questo passo viene elencato solo per completezza. Dato che non cambia la semantica, i dettagli di
questo passo non sono documentati e sono soggetti a cambiamenti senza preavviso. Questo passo viene
eseguito sull'automa a stati finiti generato durante il passo precedente.
È a questo punto che split() ottimizza silenziosamente /^/ in /^/m .
Ci sono diversi operatori di I/O che sarebbe necessario conoscere.
Una stringa racchiusa da backtick (accenti gravi) subisce inizialmente una
interpolazione a doppio quote. Poi viene interpretata come un comando
esterno, e l'output di quel comando è il valore della stringa
dei backtick, come in una shell. In contesto scalare, viene restituita
una stringa singola che consiste di tutto l'output. In contesto di lista,
viene restituita una lista di valori, uno per ogni linea di output. (Potete impostare
$/ per utilizzare un terminatore di linea differente). Il comando
viene eseguito ogni volta che viene valutato lo pseudo-letterale.
Il valore di stato del comando viene restituito in $? (per l'interpretazione di $?
si veda perlvar). Diversamente da csh, non viene
effettuata una traduzione sui dati restituiti: gli a capo rimangono a capo.
Diversamente da una qualsiasi shell, i quote singoli non proteggono i nomi di
variabile nel comando dall'interpolazione. Per passare un simbolo
letterale di dollaro alla shell, avete bisogno di nasconderlo
con un backslash. La forma generalizzata dei backtick è qx// . (Perché
anche i backtick vengono sempre sottoposti ad espansione da parte della shell, per le problematiche di
sicurezza si veda perlsec).
In contesto scalare, valutare un filehandle racchiuso nelle 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 $/ è impostato ad undef
(a volte conosciuto come modalità file-slurp) e il file è vuoto,
la prima volta restituisce '' , seguito successivamente da undef .
Di solito è necessario assegnare il valore restituito ad una variabile, ma c'è
una situazione nella quale avviene un assegnamento automatico. Se e solo se
il simbolo in input è la sola cosa all'interno della condizione di un while
(anche se travestito da for(;;) ), il valore viene automaticamente assegnato alla
variabile globale $_, distruggendo qualsiasi cosa ci fosse in precedenza.
(Questa vi potrebbe sembrare una cosa strana, ma dovrete usare il costrutto in quasi
tutti gli script Perl che scriverete). La variabile $_ non viene localizzata in modo implicito.
Se si vuole che ciò accada, dovrete mettere un local $_; prima del ciclo.
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>;
Anche questo si comporta in maniera simile, ma fa a meno di $_ :
while (my $linea = <STDIN>) { print $linea }
In questi costrutti di ciclo, il valore assegnato (se l'assegnamento
è automatico o esplicito) viene testato per vedere se
è definito. Il test defined evita 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 finale. Se davvero si vuole
terminare il ciclo per tali valori, allora devono essere testati esplicitamente:
while (($_ = <STDIN>) ne '0') { ... }
while (<STDIN>) { last unless $_; ... }
In altri contesti booleani, <filehandle senza un esplicito test
defined o un confronto, verrà segnalato
un avvertimento se vengono utilizzati la direttiva use warnings o il parametro -w
sulla linea di comando (la variabile $^W ).
I filehandle STDIN, STDOUT, e STDERR sono predefiniti. (Funzioneranno anche i
filehandle C<stdin>, C<stdout>, e C<stderr> eccetto che all'interno dei
package, dove verrebbero interpretati come identificatori locali
anzichE<eacute> globali). Tra le altre cose, possono esser creati dei filehandle addizionali
con la funzione open(). Per i dettagli si vedano L<perlopentut> e L<perlfunc/open>.
X<stdin> X<stdout> X<sterr>
Se un <FILEHANDLE> viene usato in un contesto che sta cercando
una lista, viene restituita una lista comprendente tutte le linee di input,
una linea per ciascun elemento della lista. In questo modo è facile che ciò si
sviluppi in un ammontare di spazio dati piuttosto grande, 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 elencato sulla linea di comando. Ecco come funziona:
la prima volta che <> viene valutato, viene controllato l'array @ARGV, e se
è vuoto, $ARGV[0] viene impostato a ``-'', così che quando viene aperto,
darà 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>) {
... # codice per ciascuna linea
}
}
eccetto il fatto che non è cosà scomodo da scrivere, ed in effetti funziona.
Esegue davvero lo shift sull'array @ARGV e mette il nome del 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).
È possibile modificare @ARGV prima del primo <> finché l'array termina contendendo
la lista dei nomi di file che si vogliono veramente. I numeri di linea ($. ) continuano
come se l'input fosse un unico grande file felice.
Per capire come reimpostare i numeri di linea in ogni file si veda l'esempio in perlfunc/eof.
Se si desidera impostare @ARGV alla propria lista di file, fatelo in anticipo.
Se non viene fornito @ARGV, questo inserisce in @ARGV tutti file di puro testo:
@ARGV = grep { -f && -T } glob('*') unless @ARGV;
Si può anche utilizzare @ARGV per redirigere a comandi esterni tramite pipe. Per esempio,
questo filtra automaticamente i file compressi, passati come argomento, tramite gzip:
@ARGV = map { /\.(gz|Z)$/ ? "gzip -dc < $_ |" : $_ } @ARGV;
Se si desidera passare dei parametri [le opzioni da riga di comando come --verbose, NdT] ai vostri
script, potete utilizzare uno dei moduli Getopt o inserire anteriormente un ciclo, in questo modo:
while ($_ = $ARGV[0], /^-/) {
shift;
last if /^--$/;
if (/^-D(.*)/) { $debug = $1 }
if (/^-v/) { $verboso++ }
# ... # altri parametri
}
while (<>) {
# ... # codice per ciascuna linea
}
Il simbolo <> restituirà undef per la fine-del-file una sola volta.
Se successivamente lo si chiama ancora una volta, assumerà che stiate
processando un'altra lista in @ARGV, e se non avete impostato @ARGV, leggerà
l'input da STDIN.
Se quello che le parentesi angolari contengono è semplicemente una
variabile scalare (per esempio <$pippo>), 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;
$linea = <$fh>;
Se ciò 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 che va espanso [filename pattern globbing, NdR] e, a seconda del contesto, viene
restituito o una lista di nomi di file oppure il prossimo nome del file nella lista. Questa
distinzione viene determinata su base sintattica. Cioè <$x> è sempre
una readline() da un handle indiretto, ma <$hash{chiave}> è sempre un glob().
Questo perché $x è una semplice variabile scalare, ma $hash{chiave} no: è
un elemento di hash. Anche <$x > (si noti lo spazio in più) viene
trattato come glob("$x "), non come readline($x) .
Prima viene eseguito un livello di interpretazione a doppio quote, ma non è possibile
dire <$pippo> perché questo è un filehandle indiretto, come spiegato nel
paragrafo precedente. (Nelle vecchie versioni di Perl, i programmatori
inserirebbero delle parentesi graffe per forzare l'interpretazione a glob
del nome di file: <${pippo}> . Oggi, viene considerato più pulito chiamare direttamente
la funzione interna: glob($pippo) , che in primo luogo è probabilmente la
via giusta per farlo). Per esempio:
while (<*.c>) {
chmod 0644, $_;
}
è approssivamente equivalente a:
open(PIPPO, "echo *.c | tr -s ' \t\r\f' '\\012\\012\\012\\012'|");
while (<PIPPO>) {
chomp;
chmod 0644, $_;
}
salvo che il glob venga effettivamente eseguito internamente utilizzando l'estensione standard
File::Glob . Naturalmente, la via più breve per fare quanto sopra è:
chmod 0644, <*.c>;
Un (file)glob valuta il suo argomento (incorporato) solo quando sta iniziando
una nuova lista. Tutti i valori devono essere letti prima che la lista venga reinizializzata.
In contesto di lista, questo non è importamente, perché saranno comunque ottenuti tutti
automaticamente. Tuttavia, in contesto scalare l'operatore restituisce il valore successivo ogni volta
che viene chiamato, oppure undef quando la lista è finita. Come con le letture
di un filehandle, viene generato un defined automatico quando il glob si presenta 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 una volta sola. Così se
vi state aspettando un solo valore da un glob, è molto meglio dire
($file) = <rigurgito*>;
che
$file = <rigurgito*>;
perché quest'ultimo alternerebbe la restituizione di un nome di un file con un valore falso.
Se state cercando di fare l'interpolazione di una variabile, è decisamente
meglio usare la funzione glob(), perché la vecchia notazione potrebbe indurre le persone a
confondersi con la notazione a filehandle indiretto.
@file = glob("$dir/*.[ch]");
@file = glob($file[$i]);
Come il C, Perl esegue una certa quantità 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 i letterali
che non fanno una sostituzione di variabile. Anche l'interpolazione del backslash
avviene a tempo di compilazione. Si può dire
'Abbiamo fatto l'Italia' . "\n" .
'ora dobbiamo fare gli italiani.'
e internamente tutto questo viene ridotto ad una (unica) stringa. Allo stesso modo,
se si dice
foreach $file (@nomideifile) {
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 [che non fa nulla, NdR], ma le semplici costanti
0 e 1 sono casi speciali che non producono degli avvertimenti
in constesto vuoto, in modo ad esempio da poter tranquillamente fare
1 while pippo();
Stringhe di bit di qualunque dimensione possono essere manipolate
dagli operatori bit a bit su stringhe (~ | & ^ ).
Se gli operandi di un operatore bit a bit binario sono delle stringhe
di dimensioni differenti, gli operatori | e ^ funzionano come se
l'operando più corto avesse dei bit impostati 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 è di uno o più byte.
# esempio basato su ASCII
print "j p \n" ^ " a h"; # stampa "JAPH\n" [acronimo di Just Another Perl Hacker: semplicemente un altro hacker perl, NdR]
print "JA" | " ph\n"; # stampa "japh\n"
print "japh\nJunk" & '_____'; # stampa "JAPH\n";
print 'p N$' ^ " E<H\n"; # stampa "Perl\n";
Se si ha intenzione di manipolare stringhe di bit, siate
certi che si intenda fornire stringhe di bit: se un operando è un numero,
ciò implicherà una operazione bit a bit numerica. Si può evidenziare in modo
esplicito il tipo di operazione che intendete, utilizzando "" o 0+ , come
nell'esempio qui sotto.
$pippo = 150 | 105; # produce 255 (0x96 | 0x69 e` 0xFF)
$pippo = '150' | 105; # produce 255
$pippo = 150 | '105'; # produce 255
$pippo = '150' | '105'; # produce la stringa '155' (in ASCII)
$paperino = 0+$pippo & 0+$pluto; # entrambi gli opearndi sono esplicitamente numerici
$topolino = "$pippo" ^ "$pluto"; # entrambi gli opearndi sono esplicitamente delle stringhe
Per informazioni su come manipolare singoli bit in un vettore di bit si veda perlfunc/vec.
Di default, Perl assume di dover eseguire gran parte delle operazioni
aritmetiche in virgola mobile. Ma dicendo
use integer;
si può dire al compilatore che va bene utilizzare le operazioni intere
(se se la sente) da qui alla fine del BLOCCO in cui è racchiuso.
Un BLOCCO innestato potrebbe annullare ciò dicendo
no integer;
che dura fino alla fine di quel BLOCCO. Si noti che questo non significa che
tutto è unicamente un intero, ma solo 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 giù di lì.
Usato sui numeri, gli operatori bit a bit (``&'', ``|'', ``^'', ``~'', ``<<'',
e ``>>'') producono sempre risultati interi. (Ma date un'occhiata anche a
Operatori bit a bit su stringhe.) Tuttavia, per questi operatori use integer ha ancora senso.
Di default, i loro risultati vengono interpretati come interi senza segno,
ma se è in vigore use integer , i loro risultati sono interpretati come interi con segno.
Per esempio, ~0 di solito restituisce un valore intero molto grande.
use integer; ~0 , invece, è -1 su macchine a complemento a due.
Mentre use integer fornisce solamente aritmetica per interi, non
c'è un meccanismo analogo per fornire un arrotondamento automatico
o troncamento ad 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;
# produce 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 ad
un precisato numero di cifre decimali. Per un trattamento più robusto di questo argomento
si veda Knuth, volume II.
sub fp_uguali {
my ($X, $Y, $NUMERO_CIFRE) = @_;
my ($tX, $tY);
$tX = sprintf("%.${NUMERO_CIFRE}g", $X);
$tY = sprintf("%.${NUMERO_CIFRE}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 essere specificato con precisione.
In questi casi, probabilmente è meglio non fidarsi di qualsiasi sia il
sistema di arrotondamento utilizzato dal Perl, bensì implementarsi la funzione
di arrotondamento della quale si ha bisogno.
I moduli standard Math::BigInt e Math::BigFloat forniscono
operatori aritmetici a precisione variabile e operatori overloaded [con più di un significato
della loro funzionalità, NdR], sebbene attualmente siano 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;
# stampa +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 breve, 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 velocemente vettori di bit (usa il C)
Math::BigIntFast incapsula Bit::Vector per numeri grandi
Math::Pari fornisce accesso alla libreria C Pari
Math::BigInteger usa una libreria C esterna
Math::Cephes usa la libreria C Cephes (non per numeri grandi)
Math::Cephes::Fraction frazioni attraverso la libreria Cephes
Math::GMP un altro che usa una libreria C esterna
Si scelga 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 dree, dakkar, dada.
Mon Jun 11 22:02:17 2012
|