Indice
Definizione di espressione regolare
Operazione di matching
Operazione di searching
Accesso alla matching/searching occurrence
Come scrivere un'espressione regolare
Due esempi di matching
Tre esempi di searching
Backreference esterno
Backreference interno
La funzione
re.findall()
per trovare tutte le occorrenzeLa funzione
re.sub()
per effettuare sostituzioni
Un'espressione regolare RE è una stringa di simboli che rappresenta un linguaggio (cioé un insieme di stringhe) e non se stessa.
Es: ca?t
se intesa come RE rappresenta l'insieme di due stringhe {ct
, cat
}, ma non la stringa ca?t
. Oppure ca*t
se intesa come RE rappresenta l'insieme di tutte le stringhe composte dal simbolo c
seguito da 0 o più simboli a
, seguiti dal simbolo t
. Invece ca+t
rappresenta tutte le stringhe di ca*t
tranne ct
.
Un'espressione regolare viene utilizzata in Python per compiere:
Per utilizzare un'espressione regolare si deve importare il modulo re
import re
In [2]:
import re
Data una stringa S e un'espressione regolare RE, l'operazione di matching verifica se S inizia o coincide con una delle stringhe rappresentate da RE.
L'operazione di matching ha un funzionamento greedy: considera infatti tutti i prefissi di S, a partire da quello di lunghezza massima (che coincide con S) e via via considerando quelli di lunghezza decrescente. La matching occurrence è il primo prefisso incontrato che appartiene al linguaggio di RE.
re.match()
re.match(my_expr, my_string)
restituisce un oggetto di tipo re.Match
che contiene tutte le informazioni relative all'operazione di matching tra la RE my_expr
e la stringa my_string
.
In [8]:
m = re.match('cat', 'dog and cat')
print(m)
Da notare che la RE cat
rappresenta l'unica stringa cat
(cioé la RE rappresenta se stessa). Nell'esempio precedente l'oggetto restituito dall'operazione di matching è nullo in quanto cat
non occorre come prefisso in dog and cat
.
Negli esempi successivi l'oggetto restituito dall'operazione di matching non è nullo. Nel secondo caso la matching occurrence coincide con l'intera stringa.
In [92]:
re.match('cat', 'cat and dog')
Out[92]:
In [10]:
re.match('cat', 'cat')
Out[10]:
Data una stringa S e un'espressione regolare RE, l'operazione di searching verifica se in S esiste un'occorrenza di una delle stringhe del linguaggio di RE.
L'operazione di searching ha un funzionamento greedy: la stringa S viene scandita da sinistra a destra (dal primo all’ultimo carattere). Per ogni posizione, vengono considerate tutte le sottostringhe che iniziano in quella posizione, a partire da quella di lunghezza massima (cioè si parte da un suffisso di S). La searching occurrence è la prima sottostringa incontrata che appartiene al linguaggio di RE.
re.search()
re.search(my_expr, my_string)
restituisce un oggetto di tipo re.Match
che contiene tutte le informazioni relative all'operazione di searching della RE my_expr
nella stringa my_string
.
In [3]:
re.search('cat', 'dog and cat')
Out[3]:
In [4]:
re.search('cat', 'cat and dog')
Out[4]:
In [5]:
re.search('cat', 'cat')
Out[5]:
L'oggetto di tipo re.Match
restituito da un'operazione di matching/searching mette a disposizione due metodi che permettono di ottenere la matching/searching occurrence:
Il metodo start()
restituisce la posizione di inizio (0-based) della prima occorrenza trovata.
Il metodo end()
restituisce la posizione (0-based) successiva a quella di fine della prima occorrenza trovata.
NOTA BENE: in un'operazione di matching start()
restituisce sempre 0 (ovviamente se l'oggetto restituito dall'operazione non è nullo).
In [25]:
s = re.search('cat', 'dog and cat and rat')
In [26]:
s.start()
Out[26]:
In [27]:
s.end()
Out[27]:
Per ottenere la matching occurrence basta accedere alla stringa dog and cat and rat
In [28]:
'dog and cat and rat'[s.start():s.end()]
Out[28]:
I simboli . | ( ) [ ] { } + \ ^ $ * ?
nelle RE sono metasimboli e rappresentano qualcosa di diverso da se stessi. Per fare in modo che rappresentino se stessi occorre anteporre un carattere di backslash \
. Ad esempio \?
rappresenta il punto di domanda, e quindi la RE ca\?t
rappresenta l'unica stringa ca?t.
Tutti i simboli diversi dai metasimboli precedenti rappresentano se stessi. Diventano metasimboli se gli si antepone un \
. Ad esempio \A
è il metasimbolo che specifica l'inizio di stringa (elemento di dimensione nulla prima del primo carattere della stringa).
I metasimboli permettono di specificare i seguenti elementi:
L'ancora è un elemento di dimensione nulla che può rappresentare:
^
Es: la RE ^cat
rappresenta l'unica stringa cat
con il vincolo che sia a inizio riga, e quindi occorre nelle stringhe cataaaa
e aaaa\ncataaaa
ma non in aaacataaa
, aaacat
e aaaacat\naaaa
.
$
Es: la RE cat$
rappresenta l'unica stringa cat
con il vincolo che sia a fine riga, e quindi occorre nelle stringhe aaacat
e aaaacat\naaaa
ma non in aaacataaa
, cataaa
e aaaa\ncataaaa
.
\A
Es: la RE \Acat
rappresenta l'unica stringa cat
con il vincolo che sia a inizio stringa, e quindi occorre nella stringa cataaaa
ma non in aaaa\ncataaaa
.
\z
Es: la RE cat\z
rappresenta l'unica stringa cat
con il vincolo che sia a fine stringa, e quindi occorre nella stringa aaaacat
ma non in aaaacat\naaaa
e aaaa\naaaacat\n
.
\Z
(eventualmente prima di \n
)Es: la RE cat\Z
rappresenta l'unica stringa cat
con il vincolo che sia a fine stringa (anche prima di \n
), e quindi occorre nella stringa aaaacat
e aaaa\naaaacat\n
ma non in aaaacat\naaaa
.
\b
Un simbolo di parola è un una lettera minuscola da a
a z
, oppure una lettera maiuscola da A
a Z
, oppure una cifra da 0
a 9
oppure simbolo di underscore _
.
Es: la RE \bis
rappresenta l'unica stringa is
con il vincolo che prima di i
non ci sia un simbolo di parola, e quindi occorre nella stringa It is a cat
ma non in This cat
.
\B
(negazione di \b
)Es: la RE \Bis
rappresenta l'unica stringa is
con il vincolo che prima di i
ci sia un simbolo di parola, e quindi occorre nella stringa This cat
ma non in It is a cat
.
Una classe è un insieme di caratteri, e viene specificata tra due parentesi quadre []
in uno dei seguenti modi:
Es: [aeiou]
rappresenta la classe delle vocali minuscole. [.;:,]
rappresenta la classe dei simboli di punteggiatura (in questo caso il simbolo .
non è un metasimbolo). [?\b]
rappresenta la classe dei due simboli ?
e backspace.
-
.Es: [a-z]
è la classe delle lettere minuscole. [a-zA-Z]
è la classe di tutte le lettere. [a-zA-Z0-9_]
è la classe di tutti i simboli di parola.
NOTA BENE: [a\-z]
è la classe dei tre simboli a
, -
e z
.
Il simbolo ^
messo subito dopo la prima parentesi [
permette di effettuare la negazione di ciò che viene specificato dopo.
Es: [^aeiou]
è la classe di tutto ciò che non è vocale minuscola. [^a-zA-Z0-9_]
è la classe di tutti i simboli che non sono di parola.
NOTA BENE: [ae^iou]
è la classe delle vocali minuscole e del simbolo ^
.
Una classe rappresenta ognuno dei simboli che le appartengono.
Es: la RE [A-Z]at
rappresenta le stringhe Cat
, Rat
e Bat
ma non le stringhe cat
, rat
e bat
(che invece sono rappresentate dalle RE [a-z]at
e [a-zA-Z]at
.
Per alcune classi esiste un metasimbolo scorciatoia:
\d
equivalente alla classe [0-9]
(cifra decimale)\D
equivalente alla classe per[^0-9]
(negazione di \d
)\w
equivalente alla classe [a-zA-Z0-9_]
(simbolo di parola)\W
equivalente alla classe [^a-zA-Z0-9_]
(negazione di \w
)\h
equivalente alla classe [0-9a-fA-F]
(cifra esadecimale)\H
equivalente alla classe [^0-9a-fA-F]
(negazione di \h
)\s
equivalente alla classe [␣\t\r\n\f]
(tutto ciò che è spazio)\S
equivalente alla classe [^␣\t\r\n\f]
(negazione di \s
).
equivalente alla classe [^\n]
(qualsiasi carattere eccetto \n
)Un raggruppamento è una parte di RE specificato all'interno di parentesi tonde ()
che può:
Es: la RE a(bc)d
contiene il raggruppamento (bc)
.
Un quantificatore specifica il numero di volte con cui il carattere, la classe o il raggruppamento che lo precedono possono manifestarsi all'interno del stringa con cui la RE viene confrontata. Un quantificatore può specificare:
*
Es: la RE ca*t
rappresenta le stringhe ct
e cat
, caat
, caaat
, etc., cioé le stringhe composte da c
, seguita da zero o più simboli a
, seguiti da t
.
+
Es: la RE ca+t
rappresenta le stringhe cat
, caat
, caaat
, etc., ma non ct
, cioé le stringhe composte da c
, seguita da uno o più simboli a
, seguiti da t
.
Es: La RE c[ab]+t
rappresenta tutte le stringhe composte da un simbolo c
seguito da una o più ripetizioni del simbolo a
oppure b
seguite dal simbolo t
. Quindi ad esempio la stringa caabbbabababbat
appartiene al linguaggio della RE.
Es: La RE c(ab)+t
rappresenta le stringhe cabt
, cababt
, cabababt
, etc., cioé le stringhe composte da c
, seguita da una o più ripetizioni di ab
, seguite da t
.
?
Es: la RE ca?t
rappresenta le sole stringhe ct
e cat
.
m
a n
ripetizioni {m,n}
Es: la RE ca{2,5}t
rappresenta le sole stringhe caat
, caaat
, caaaat
e caaaaat
, composte da c
, seguita da due, o quattro, o cinque simboli a
, seguiti da t
.
m
ripetizioni {m,}
Es: la RE ca{2,}t
rappresenta le stringhe caat
, caaat
, caaaat
, caaaaat
, etc., composte da c
, seguita da almeno due a
, seguiti da t
.
n
ripetizioni {,n}
Es: la RE ca{,5}t
rappresenta le sole stringhe ct
, cat
, caat
caaat
, caaaat
e caaaaat
, composte da c
, seguita da al più cinque simboli a
, seguiti da t
.
m
ripetizioni {m}
Es: la RE ca{5}t
rappresenta la sola stringa caaaaat
, composte da c
, seguita da cinque simboli a
, seguiti da t
.
Un'alternativa specifica la possibilità tra due parti della RE, e viene specificata tramite il metasimbolo |
.
Es: la RE ab|cd
rappresenta il linguaggio {ab
, cd
}.
NOTA BENE: il simbolo |
viene valutato per ultimo e quindi la RE cane nero|bianco
corrisponde al linguaggio {cane nero
, bianco
} e non al linguaggio {cane nero
, cane bianco
} . La RE che corrisponde al linguaggio {cane nero
, cane bianco
} è invece cane (nero|bianco)
.
Il backreference interno crea la connessione tra diverse parti della RE.
I metasimboli \\1
, \\2
, \\3
etc., specificano una connessione con i raggruppamenti presenti nella RE da usare in operazioni di matching, searching o sostituzione. Precisamente \\1
si riferisce al primo raggruppamento a partire da sinistra, \\2
si riferisce al secondo, etc.
Es: nella RE (\w+)\s\\1
è presente unicamente il metasimbolo \\1
che si riferisce all'unico raggruppamento presente.
Si consideri la stringa:
In [104]:
stringa = '***hello world***'
Si effettui il searching della RE \w+
che rappresenta tutte le stringhe composte da uno o più simboli di parola.
In [105]:
s = re.search('\w+', stringa)
La searching occurrence è:
In [106]:
stringa[s.start():s.end()]
Out[106]:
Se si vuole fare in modo che la searching occurrence sia hello world
si deve operare il searching con la RE \w+\s\w+
che rappresenta tutte le stringhe composte da uno o più simboli di parola seguiti da uno spazio e poi ancora da uno o più simboli di parola.
In [107]:
s = re.search('\w+\s\w+', stringa)
La searching occurrence è ora:
In [108]:
stringa[s.start():s.end()]
Out[108]:
Si cambi ora la stringa in ***hello world***
mantenendo la stessa RE.
In [109]:
stringa = '***hello world***'
s = re.search('\w+\s\w+', stringa)
L'operazione di searching restituisce ora un oggetto nullo.
In [110]:
stringa[s.start():s.end()]
La RE che permette di catturare hello world
(con un qualsiasi numero di spazi tra hello
e world
) è \w+\s+\w+
.
In [111]:
s = re.search('\w+\s+\w+', stringa)
La searching occurrence è infatti:
In [112]:
stringa[s.start():s.end()]
Out[112]:
Si provi ora a usare la RE .+
che rappresenta tutte le stringhe di uno o più caratteri qualsiasi (tranne il newline \n
).
In [113]:
s = re.search('.+', stringa)
La searching occurrence è ora l'intera stringa.
In [114]:
stringa[s.start():s.end()]
Out[114]:
A questo punto si inserisca nella stringa un carattere di newline \n
dopo hello
e si operi il searching della RE .+
.
In [115]:
stringa = '***hello\n world***'
s = re.search('.+', stringa)
La searching occurrence diventa:
In [116]:
stringa[s.start():s.end()]
Out[116]:
in quanto il simbolo \n
non appartiene alla classe rappresentata dal metasimbolo .
.
Si consideri la stringa bbbcaaaaaaaatcaaaat
.
In [117]:
stringa = 'bbbcaaaaaaaatcaaaat'
Si effettui il searching della RE (ca)+
che rappresenta tutte le stringhe composte da ca
ripetuto almeno una volta.
In [118]:
s = re.search('(ca)+', stringa)
La searching occurrence è:
In [119]:
stringa[s.start():s.end()]
Out[119]:
che inizia in posizione:
In [120]:
s.start()
Out[120]:
e finisce in posizione:
In [121]:
s.end()
Out[121]:
Si tolgano ora le parentesi tonde ()
e si effettui il searching della RE ca+
che rappresenta tutte le stringhe composte da c
seguita da una o più a
.
In [122]:
s = re.search('ca+', stringa)
La searching occurrence è:
In [123]:
stringa[s.start():s.end()]
Out[123]:
che inizia in posizione:
In [124]:
s.start()
Out[124]:
e finisce in posizione:
In [125]:
s.end()
Out[125]:
La searching occurrence, a causa del comportamento greedy dell'operazione, si estende il più a destra possibile. Per annullare questo comportamento e limitare al minimo la lunghezza, basta inserire il metasimbolo ?
subito dopo il quantificatore +
.
In [78]:
s = re.search('ca+?', stringa)
La searching occurrence è ora:
In [79]:
stringa[s.start():s.end()]
Out[79]:
Si provi ora a sostituire il quantificatore +
con *
e a usare quindi la RE ca*
che rappresenta tutte le stringhe composte da c
seguita da zero o più a
.
In [80]:
s = re.search('ca*', stringa)
La searching occurrence è:
In [81]:
stringa[s.start():s.end()]
Out[81]:
Si aggiunga un ?
subito dopo il quantificatore *
.
In [82]:
s = re.search('ca*?', stringa)
La searching occurrence diventa:
In [83]:
stringa[s.start():s.end()]
Out[83]:
Il meccanismo di backreference esterno permette di catturare parti della searching/matching occurrence e di usarle all'esterno dell'operazione di matching/searching.
Requisito*: la RE deve contenere i raggruppamenti delle parti da catturare. I raggruppamenti sono indicizzati da sinistra a destra a partire da 1 (0 è l’indice di default dell’intera matching/searching occurrence).
il metodo group()
degli oggetti di tipo re.Match
restituisce la parte di matching/searching occurrence relativa al raggruppamento il cui indice viene specificato come argomento. Se group()
viene invocato senza argomento, allora assume che l’indice sia 0 (quello di default) e quindi restituisce l'intera matching/searching occurrence.
NOTA BENE: anche i metodi start()
ed end()
possono prendere come argomento l'indice di un raggruppamento, e in tale caso restituiscono lo start e l'end della parte catturata.
La RE dell'esempio seguente contiene due raggruppamenti.
In [126]:
s = re.search('(\w+)\s+(\w+)', 'gatto cane')
La searching occurrence è:
In [127]:
s.group()
Out[127]:
La parte catturata dal primo raggruppamento è:
In [128]:
s.group(1)
Out[128]:
e inizia in posizione:
In [129]:
s.start(1)
Out[129]:
La parte catturata dal secondo raggruppamento è:
In [130]:
s.group(2)
Out[130]:
e inizia in posizione:
In [131]:
s.start(2)
Out[131]:
Ad esempio la RE (\w+)\s+\\1
rappresenta tutte le stringhe composte da uno o più caratteri di parola, seguiti da uno o più spazi, seguiti dalla stessa stringa che il primo raggruppamento cattura nell'operazione di searching. Quindi (\w+)\s+\\1
occorre nella stringa gatto gatto
ma non nella stringa gatto cane
:
In [132]:
s = re.search('(\w+)\s+\\1', 'gatto gatto')
La searching occurrence è:
In [133]:
s.group(1)
Out[133]:
Se invece si usa la stringa gatto cane
:
In [136]:
s = re.search('(\w+)\s+\\1', 'gatto cane')
In [137]:
s.group(1)
Altro esempio:
In [7]:
s = re.search('(\w+)\\1', 'Mississippi')
La searching occurrence è:
In [8]:
s.group()
Out[8]:
La funzione:
re.findall(my_expr, my_string)
trova tutte le occorrenze non sovrapposte della RE my_expr
nella stringa my_string
, e restituisce:
In [20]:
re.findall('\w\w', 'abcdefgh')
Out[20]:
In [21]:
re.findall('(\w)\w', 'abcdefgh')
Out[21]:
In [22]:
re.findall('(\w)(\w)', 'abcdefgh')
Out[22]:
In [23]:
re.findall('((\w)(\w))', 'abcdefgh')
Out[23]:
Il seguente esempio mostra come separare una stringa usando come delimitatore tutto ciò che non è simbolo di parola.
In [92]:
re.findall('\w+', 'cat dog mouse pig')
Out[92]:
Il seguente esempio mostra come separare una stringa usando come delimitatore tutto ciò che non è simbolo di parola e ammettendo uno spazio tra due parole.
In [93]:
re.findall('\w+\s+\w+', 'cat dog mouse pig')
Out[93]:
Si aggiungano ora dei raggruppamenti.
In [94]:
re.findall('(\w+)\s+\w+', 'cat dog mouse pig')
Out[94]:
In [95]:
re.findall('(\w+)\s+(\w+)', 'cat dog mouse pig')
Out[95]:
La funzione:
re.sub(my_expr, r_string, my_string)
restituisce la stringa ottenuta sostituendo con r_string
tutte le occorrenze non sovrapposte di my_expr
in my_string
.
In [145]:
re.sub('\w+\s\w+', 'goose', 'cat dog mouse pig')
Out[145]: