index | project | pods | responsabili

NOME

perlrequick - Guida rapida alle espressioni regolari del Perl


DESCRIZIONE

Questa pagina descrive gli elementi di base per quanto riguarda la comprensione, la creazione e l'uso delle espressioni regolari (regex) in Perl.


La Guida

Il semplice match di una parola

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 '/' [rispetto alla prima, NdT] 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

L'utilizzo di classi di caratteri

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 modalita` case-insensitive
                    # 'yes', 'Yes', 'YES', ecc.
    /yes/i;         # anche questo matcha 'yes' in modalita` 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` normale

Il Perl ha diverse abbreviazioni per le classi di caratteri comuni:

  • \d è una cifra e rappresenta [0-9]

  • \s è uno spazio bianco e rappresenta [\ \t\r\n\f]

  • \w è un carattere di una parola (alfanumerico o _) e rappresenta [0-9a-zA-Z_]

  • \D è una \d negata; rappresenta ogni carattere ad esclusione di una cifra [^0-9]

  • \S è una \s negata; rappresenta ogni carattere che non sia uno spazio bianco [^\s]

  • \W è una \w negata; rappresenta ogni carattere che non appartenga ad una parola (???) [^\w]

  • Il punto '.' matcha ogni carattere ad esclusione del ``\n''

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.

Matchare questo o quello

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.

Raggruppamenti di cose e match gerarchico

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

L'estrazione di match

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.

Ripetizioni di match

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 piu` spazi di lunghezza 
                     # arbitraria
    $year =~ /\d{2,4}/;  # si assicura che l'anno sia almeno di 2 cifre ma non piu`
                         # 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 match)

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.

Ulteriore matching

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'; # effettua un match di '$pattern', non di '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'

Ricerca e sostituzione

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]

L'operatore split

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 viene 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.


BUG

Nessuno.


SI VEDA ANCHE

Questa è solo una guida rapida. Per un corso più approfondito sulle regex, guardate perlretut e per la pagina di reference, guardate perlre.


AUTORE E COPYRIGHT

Copyright (c) 2000 Mark Kvale Tutti i diritti riservati.

Questo documento può essere distribuito secondo gli stessi termini del Perl.

Riconoscimenti

L'autore vuole ringraziare Mark-Jason Dominus, Tom Christiansen, Ilya Zakharevich, Brad Hughes e Mike Giroux per tutti i loro utili commenti.


TRADUZIONE

Versione

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/ .

Traduttore

Traduzione a cura di dree.

Revisore

Revisione a cura di Marco Allegretti.


Mon Jun 11 22:02:18 2012