NOME |
perlrequick - Guida rapida alle espressioni regolari del Perl
Questa pagina descrive gli elementi di base per quanto riguarda la comprensione, la creazione e l'uso delle espressioni regolari (regex) in Perl.
La regex più semplice è semplicemente una parola, o più in generale, una stringa di caratteri. Una regex che consiste in una parola, matcha ogni stringa che contiente quella parola:
"Ciao Mondo" =~ /Mondo/; # matcha
In questa asserzione (statement), Mondo
è una regex e il //
che racchiude
/Mondo/
dice a perl di cercare una stringa per un match. L'operatore
=~
associa la stringa con il match della regex e produce un valore vero
se la regex matcha, o falso se la regex non matcha. Nel
nostro caso, Mondo
matcha la seconda parola in "Ciao Mondo"
, quindi
l'espressione è vera. Questa idea ha diverse varianti.
Le espressioni come questa sono molto utili nei condizionali:
print "Questo matcha\n" if "Ciao Mondo" =~ /Mondo/;
Il senso del match può essere invertito usando l'operatore !~
:
print "Questo non matcha\n" if "Ciao Mondo" !~ /Mondo/;
La stringa letterale nella regex può essere sostituita da una variabile:
$saluti = "Mondo"; print "Questo matcha\n" if "Ciao Mondo" =~ /$saluti/;
Se stai facendo matching attraverso $_
, la parte $_ =~
può essere omessa:
$_ = "Ciao Mondo"; print "Questo matcha\n" if /Mondo/;
Infine, i //
, delimitatori di default per un match, possono essere
sostituiti con delimitatori arbitrari, utilizzando un 'm'
out front:
"Ciao Mondo" =~ m!Mondo!; # matcha, delimitato da '!' "Ciao Mondo" =~ m{Mondo}; # matcha, da notare the matching '{}' "/usr/bin/perl" =~ m"/perl"; # matcha dopo '/usr/bin', # '/' diventa un carattere qualsiasi
Le regex devono effettuare un match della parte di una stringa esattamente affinché l'asserzione (statement) sia vera:
"Ciao Mondo" =~ /mondo/; # non matcha, case sensitive "Ciao Mondo" =~ /o M/; # matcha, ' ' e` un carattere qualsiasi "Ciao Mondo" =~ /Mondo /; # non matcha, non c'e` un ' ' alla fine
perl effettuerà sempre un match nel punto della stringa più vicino:
"Ciao Mondo" =~ /o/; # matcha 'o' in 'Ciao' "That hat is red" =~ /hat/; # matcha 'hat' in 'That' [Questo cappello e` rosso, NdT]
Non tutti i caratteri possono essere usati 'letteralmente' in un match. Alcuni caratteri chiamati metacaratteri, sono riservati per utilizzarli nella notazione delle regex. I metacaratteri sono
{}[]()^$.|*+?\
Un metacarattere può essere matchato inserendo un backslash prima di lui:
"2+2=4" =~ /2+2/; # non matcha, + e` un metacarattere "2+2=4" =~ /2\+2/; # matcha, \+ e` trattato come un semplice + 'C:\WIN32' =~ /C:\\WIN/; # matcha "/usr/bin/perl" =~ /\/usr\/local\/bin\/perl/; # matcha
Nell'ultima regex, le successive slash '/'
(N.di T. rispetto alla prima)
sono anche precedute da backslash, perché sono usato per delimitare
la regex.
I caratteri ASCII non stampabili sono rappresentati da sequenze di escape.
Esempi comuni sono \t
per il tab, \n
per il newline, e \r
per il carriage return. I byte arbitrari sono rappresentati da sequenze
di escape ottali, ad es., \033
, o sequenze di escape esadecimali,
ad es., \x1B
:
"1000\t2000" =~ m(0\t2) # matcha "cat" =~ /\143\x61\x74/ # matcha, ma e` un modo bizzarro per pronunciare gatto
Le regex sono trattate principalmente come stringhe tra doppi apici, quindi funziona la sostituzione di variabile:
$pippo = 'cassa'; 'grancassa' =~ /gran$pippo/; # matcha 'cassagran' =~ /${pippo}gran/; # matcha
In tutte le regex viste sopra, se la regex matcha ovunque nella stringa,
viene considerato un match. Per speficicare dove dovrà effettuare il match,
useremo i metacaratteri ancora ^
e $
. L'ancora ^
indica che il match
sarà effettuato all'inizio della stringa e l'ancora $
indica il match alla fine
della stringa, o prima di un newline alla fine della stringa. Alcuni esempi:
"donna di casa" =~ /casa/; # matcha "donna di casa" =~ /^casa/; # non matcha "donna di casa" =~ /casa$/; # matcha "donna di casa\n" =~ /casa$/; # matcha "donna di casa" =~ /^donna di casa$/; # matcha
Una classe di caratteri permette ad un insieme di possibili caratteri, piuttosto
che un solo singolo carattere, di essere matchati ad un punto particolare in una regex.
Le classi di caratteri sono denotate da parentesi quadre [...]
, con all'interno
l'insieme di caratteri che possono essere matchati. Qui c'è qualche esempio:
/gatto/; # matcha 'gatto' /[pgr]atto/; # matcha 'patto', 'gatto', or 'ratto' "abc" =~ /[cab]/; # matcha 'a'
Nell'ultima asserzione (statement), anche se 'c'
è il primo carattere
nella classe, il primissimo punto dove la regex può effettuare il match
è 'a'
.
/[yY][eE][sS]/; # matcha 'yes' in modalitE<agrave> case-insensitive # 'yes', 'Yes', 'YES', etc. /yes/i; # anche questo matcha 'yes' in modalitE<agrave> case-insensitive way
[sì, NdT]
L'ultimo esempio mostra una match con un modificatore 'i'
, che rende
il match case-insensitive.
Le classi di caratteri possiedono sia caratteri normali (ordinary) che speciali,
ma gli insiemi di caratteri normali e speciali all'interno di una classe di
caratteri sono differenti rispetto a quelli al di fuori di una classe di
caratteri. I caratteri speciali per una classe di caratteri sono -]\^$
e
sono matchati usando un escape:
/[\]c]def/; # matcha ']def' or 'cdef' $x = 'bcr'; /[$x]at/; # matcha 'bat, 'cat', or 'rat' [pipistrello, gatto, ratto, NdT] /[\$x]at/; # matcha '$at' or 'xat' /[\\$x]at/; # matcha '\at', 'bat, 'cat', or 'rat'
Il carattere speciale '-'
opera come un operatore di intervallo all'interno delle
classi di caratteri, così che le poco maneggevoli [0123456789]
e [abc...xyz]
diventino le agili [0-9]
e [a-z]
:
/item[0-9]/; # matcha 'item0' o ... o 'item9' /[0-9a-fA-F]/; # matcha un numero esadecimale
Se '-'
è il primo o l'ultimo carattere in una classe di caratteri, esso
viene trattato come un carattere normale.
Il carattere speciale ^
nella prima posizione di una classe di caratteri
denota una classe di caratteri negata, che matcha ogni carattere ad esclusione di
quelli tra le parentesi quadre. Sia [...]
che [^...]
devono matchare un
carattere, o il match fallisce. Dunque
/[^a]at/; # non matcha 'aat' or 'at', ma matcha # tutti gli altri 'bat', 'cat, '0at', '%at', etc. /[^0-9]/; # matcha un carattere non numerico /[a^]at/; # matcha 'aat' o '^at'; qui '^' E<egrave> normale
Il Perl ha diverse abbreviazioni per le classi di caratteri comuni:
Le abbreviazioni \d\s\w\D\S\W
possono essere usate sia all'interno che all'esterno delle
classi di caratteri. Qui ci sono alcuni utilizzi:
/\d\d:\d\d:\d\d/; # matcha un formato tempo hh:mm:ss /[\d\s]/; # matcha ogni numero o spazio /\w\W\w/; # matcha un carattere normale, seguito # da un carattere di formattazione, seguito da un carattere normale /..rt/; # matcha due caratteri qualunque, seguiti da 'rt' /end\./; # matcha 'end.' [fine, NdT] /end[.]/; # stessa cosa, matcha 'end.'
L'ancora di parola \b
matcha un confine tra un carattere di parola
e un carattere di non-parola \w\W
o \W\w
:
$x = "Housecat catenates house and cat"; [Casagatto concatena casa e gatto, NdT] $x =~ /\bcat/; # matcha cat in 'catenates' $x =~ /cat\b/; # matcha cat in 'housecat' $x =~ /\bcat\b/; # matcha 'cat' alla fine della stringa
Nell'ultimo esempio la fine della stringa viene considerata un confine di parola.
Possiamo effettuare il match di differenti stringhe di caratteri con il
metacarattere '|'
. Per effettuare il match di cane
o gatto
, formiamo la regex
cane|gatto
. Come prima, perl cercherà di effettuare il match della regex
al primissimo punto possibile nella stringa. Ad ogni posizione di un cartattere,
perl cercherà prima di effettuare il macht della prima alternativa, cane
. Se
cane
non matcha, perl tenterà allora la seconda alternativa, gatto
.
Se gatto
non matcha ancora, allora il match fallisce e perl si sposterà
alla prossima posizione nella stringa. Alcuni esempi:
"cats and dogs" =~ /cat|dog|bird/; # matcha "cat" [cani e gatti, cane|gatto|uccello, NdT] "cats and dogs" =~ /dog|cat|bird/; # matcha "cat"
Anche se cane
è la prima alternativa nella seconda regex,
gatto
è in grado di effettuare il match all'inizio della stringa.
"cats" =~ /c|ca|cat|cats/; # matcha "c" "cats" =~ /cats|cat|ca|c/; # matcha "cats"
Ad una data posizione di un carattere, la prima alternativa che permette al match della regex di avere successo sarà quella che effettuerà il match. Qui, tutte le alternative matchano alla prima posizione della stringa, così la prima di esse matcha per prima.
I metacaratteri di raggruppamento ()
permettono ad una parte di regex
di essere trattata come una singola unità. Parti di una regex sono raggruppati
racchiudendole tra parentesi tonde. La regex house(cat|keeper)
ha il significto di
effettuare il match di house
seguito o da cat
o da keeper
. Ulteriori esempio
sono
/(a|b)b/; # matcha 'ab' o 'bb' /(^a|b)c/; # matcha 'ac' all'inizio della stringa o 'bc' ovunque
/house(cat|)/; # matcha sia 'housecat' che 'house' /house(cat(s|)|)/; # matcha sia 'housecats' sia 'housecat' sia # 'house'. Va notato che i raggruppamenti possono essere annidati.
"20" =~ /(19|20|)\d\d/; # matcha l'alternativa nulla '()\d\d', # perche' '20\d\d' non puo` matchare
I metacaratteri di raggruppamento ()
permettono anche l'estrazione
delle parti della stringa che sono state matchate. Per ogni raggruppamento,
la parte che viene matchata all'interno va nelle variabili speciali
$1
, $2
, ecc.
Esse possono essere usate proprio come variabili ordinarie:
# estrae ore, minuti, secondi $tempo =~ /(\d\d):(\d\d):(\d\d)/; # matcha il formato hh:mm:ss $ore = $1; $minuti = $2; $secondi = $3;
In un contesto di lista, un match /regex/
con raggruppamenti,
restituirà la lista dei valori matchati ($1,$2,...)
.
Dunque potremmo riscriverla come
($ore, $minuti, $secondi) = ($tempo =~ /(\d\d):(\d\d):(\d\d)/);
Se i raggruppamenti in una regex sono nidificati, $1
prende il gruppo
con le parentesi aperte più a sinistra, $2
la seguente parentesi aperta
ecc. Per esempio, qui c'è una complessa regex e le variabili di match
indicate sotto ad essa:
/(ab(cd|ef)((gi)|j))/; 1 2 34
Associati con le variabili di match $1
, $2
, ... sono le
backreference \1
, \2
, ... Le backreference sono
variabili di match che possono essere usate dentro una regex:
/(\w\w\w)\s\1/; # trova le sequenze tipo 'uno uno' nella stringa
$1
, $2
, ... dovrebbero essere usate solo fuori da una regex, e \1
,
\2
, ... solo dentro una regex.
I metacaratteri quantificatori ?
, *
, +
, e {}
ci permettono
di determinare il numero di ripetizioni di una regex che consideriamo essere
un match. I quantificatori vengono messi immediatamente dopo il carattere,
la classe di carattere, o il raggruppamento che vogliamo specificare. Essi
hanno i seguenti significati:
a?
= matcha 'a' 1 o 0 volte
a*
= matcha 'a' 0 o più volte, cioè, un numero qualsiasi di volte
a+
= matcha 'a' 1 o più volte, cioè, almeno una
a{n,m}
= matcha almeno n
volte, ma non più di m
volte.
a{n,}
= matcha almeno n
o più volte
a{n}
= matcha esattamente n
volte
Qui ci sono alcuni esempi:
/[a-z]+\s+\d*/; # matcha una parola formata da lettere minuscole, almeno uno spazio, e # un numero qualsiasi di cifre /(\w+)\s+\1/; # matcha parole doppie separate da uno o piE<ugrave> spazi di lunghezza # arbitraria $year =~ /\d{2,4}/; # si assicura che l'anno sia almeno di 2 cifre ma non piE<ugrave> # di 4 cifre $year =~ /\d{4}|\d{2}/; # un match migliore; scarta date con 3 cifre
Questi quantificatori cercano di matchare più stringa possibile, mentre si sta ancora permettendo alla regex di mathcare. Dunque abbiamo
$x = 'the cat in the hat'; [il gatto nel cappello, NdT] $x =~ /^(.*)(at)(.*)$/; # matcha, # $1 = 'the cat in the h' # $2 = 'at' # $3 = '' (0 matches)
Il primo quantificatore .*
cattura quanto più della stringa è possibile
mentre la regex continua a matchare. Il secondo quantificatore .*
non ha
più stringa alla sua sinistra, dunque esso matcha 0 volte.
Ci sono ancora alcune cose che si devono conoscere sugli operatori di matching. Nel codice
$pattern = 'Seuss'; while (<>) { print if /$pattern/; }
perl deve ri-valutare ogni volta $pattern
all'interno del loop. Se
$pattern
non sarà cambiato, si usi il modificatore //o
, per eseguire la
sostituzione di variabile una volta sola. Se non si vuole del tutto alcuna
sostituzione. si usi lo speciale delimitatore m''
:
$pattern = 'Seuss'; m'$pattern'; # matches '$pattern', not 'Seuss'
Il modificatore globale //g
permette agli operatori di matching di
matchare all'interno di una stringa il numero più alto di volte possibile.
In un contesto scalare, i successivi match su di una stringa avranno //g
salti da match a match, tenendo traccia della posizione nella stringa raggiunta.
Si può leggere o settare la posizione con la funzione pos()
.
Per esempio,
$x = "cat dog house"; # 3 words while ($x =~ /(\w+)/g) { print "La parola $1, finisce alla posizione ", pos $x, "\n"; }
stampa
La parola cat, finisce alla posizione 3 La parola dog, finisce alla posizione 7 La parola house, finisce alla posizione 13
Un match fallito o il cambiamento della stringa obiettivo, resetta la posizione.
Se non si vuole che la posizione venga resettata dopo il fallimento del match, si
aggiunga la //c
, come in /regex/gc
.
In un contesto di lista, //g
restituisce una lista di reggruppamenti matchati, o se
non ci sono raggruppamenti, una lista di match all'intera regex. Così
@words = ($x =~ /(\w+)/g); # matcha, # $word[0] = 'cat' # $word[1] = 'dog' # $word[2] = 'house'
La ricerca e la sostituzione sono effettuate usando s/regex/sostituzione/modificatori
.
La sostituzione
è una stringa Perl double quoted che sostituisce nella stringa
qualsiasi cosa sia matchata con la regex
. L'operatore =~
, qui è anche usato
per associare una stringa con s///
. Se il match è verso $_
, la $_ =~
può essere omessa.
Se c'è un match,s///
restituisce il numero delle sostituzioni fatte, altrimenti
restituisce falso.
Qui di seguito alcuni esempi:
$x = "Time to feed the cat!"; [E` ora di dar da mangiare al gatto, NdT] $x =~ s/cat/hacker/; # $x contiene "Time to feed the hacker!" $y = "'quoted words'"; [parole tra doppie virgolette, NdT] $y =~ s/^'(.*)'$/$1/; # elimina gli apici singoli, # $y contiene "quoted words"
Con l'operatore s///
,le variabili matchate $1
, $2
, ecc.
sono immediatamente disponibili per l'uso nell'espressione di sostituzione.
Con il modificatore globale, s///g
cercherà e sostituirà tutte le
occorrenze della regex nella stringa:
$x = "I batted 4 for 4"; [Ho fatto 4 battute su 4, NdT] $x =~ s/4/four/; # $x contiene "I batted four for 4" $x = "I batted 4 for 4"; $x =~ s/4/four/g; # $x contiene "I batted four for four"
Il modificatore di valutazione s///e
pone un eval{...}
attorno alla stringa
di sostituzione e il risultato valutato viene sostituito alla sottostringa matchata.
Ecco alcuni esempi:
# inverte tutte le lettere in una stringa $x = "the cat in the hat"; $x =~ s/(\w+)/reverse $1/ge; # $x contains "eht tac ni eht tah"
# converte una percentuale in decimale $x = "A 39% hit rate"; [Una percentuale di battuta del 39%, NdT] $x =~ s!(\d+)%!$1/100!e; # $x contains "A 0.39 hit rate"
L'ultimo esempio mostra che s///
può usare altri delimitatori, quali
s!!!
e s{}{}
, ed anche s{}//
. Se vengono utilizzate le virgolette singole
s'''
, allora la regex e la sostituzione sono trattate come stringhe single quoted.
[delimitate da virgolette singole, NdT]
split /regex/, stringa
divide la stringa
in una lista di sottostringhe
e restituisce tale lista. La regex determina la sequenza di caratteri
per i quali la stringa
�divisa. Per esempio, per dividere una stringa in parole,
si usi
$x = "Calvin and Hobbes"; @word = split /\s+/, $x; # $word[0] = 'Calvin' # $word[1] = 'and' [e, NdT] # $word[2] = 'Hobbes'
Per estrarre una lista di numeri separati da virgola, si usi
$x = "1.618,2.718, 3.142"; @const = split /,\s*/, $x; # $const[0] = '1.618' # $const[1] = '2.718' # $const[2] = '3.142'
Se viene usata la regex vuota //
, la stringa viene divisa in singoli caratteri.
Se la regex ha dei raggruppamenti, allora la lista prodotta contiene la sottostringa
matchata e anche gli elementi divisori:
$x = "/usr/bin"; @parts = split m!(/)!, $x; # $parts[0] = '' # $parts[1] = '/' # $parts[2] = 'usr' # $parts[3] = '/' # $parts[4] = 'bin'
Dato che il primo carattere di $x matcha la regex, split
prepone
un elemento iniziale vuoto alla lista.
Nessuno.
Questa è solo una guida rapida. Per un corso più approfondito sulle regex, guardate the perlretut manpage e per la pagina di reference, guardate the perlre manpage.
Copyright (c) 2000 Mark Kvale Tutti i diritti riservati.
Questo documento può essere distribuito secondo gli stessi termini del Perl.
L'autore vuole ringraziare Mark-Jason Dominus, Tom Christiansen, Ilya Zakharevich, Brad Hughes e Mike Giroux per tutti i loro utili commenti.
La versione su cui si basa questa traduzione è ottenibile con:
perl -MPOD2::IT -e print_pod perlrequick
Per maggiori informazioni sul progetto di traduzione in italiano si veda http://pod2it.sourceforge.net/ .
Traduzione a cura di dree.
Revisione a cura di Marco Allegretti.
NOME |