metodo per verificare se una stringa ha una certa forma
esempio: elenco telefonico
cerchiamo "Mario":
import re
elenco='Luca Rossi 2345234 - Mario Bianchi 82342342 - Marco Verdi 342342342'
m = re.search('Mario', elenco)
if m:
print("trovato")
else:
print("not trovato")
if m:
print("trovato")
else:
print("not trovato")
dice solo se il nome c'è o meno
non dà il numero di telefono
import re
elenco='Luca Rossi 2345234 - Mario Bianchi 82342342 - Marco Verdi 342342342'
m = re.search('Mario', elenco)
if m:
print("trovato: " + m.group())
else:
print("not trovato")
m.group() è la stringa trovata
trovato: Mario
non c'è il telefono!
import re
elenco='Luca Rossi 2345234 - Mario Bianchi 82342342 - Marco Verdi 342342342'
m = re.search('Mario', elenco)
if m:
print("trovato: " + m.group())
else:
print("not trovato")
m = re.search('Mario', elenco) = cerca la stringa 'Mario' in elenco
serve nome+telefono!
elenco='Luca Rossi 2345234 - Mario Bianchi 82342342 - Marco Verdi 342342342'
m = re.search('Mario Bianchi 82342342', elenco)
…
vorrebbe dire che già sappiamo il telefono
quello che cerchiamo:
Mario … -
cos'è '…' qui?
formato dell'elenco:
elenco='Luca Rossi 2345234 - Mario Bianchi 82342342 - Marco Verdi 342342342'
cerchiamo:
Mario seguito da caratteri, spazi e cifre
basta che non ci sia -
m = re.search('Mario[a-zA-Z0-9 ]*', elenco)
quindi:
[a-zA-Z0-9 ]* è una sequenza di lettere, cifre e spazi
import re
elenco='Luca Rossi 2345234 - Mario Bianchi 82342342 - Marco Verdi 342342342'
m = re.search('Mario[a-zA-Z0-9 ]*', elenco)
if m:
print("trovato: " + m.group())
else:
print("not trovato")
stampa:
trovato: Mario Bianchi 82342342
elenco='Luca Rossi 2345234 - Mario Bianchi 82342342 - Marco Verdi 342342342'
in questo caso:
[a-zA-Z0-9 ] = caratteri qualsiasi tranne -
espressione: [^-]
import re
elenco='Luca Rossi 2345234 - Mario Bianchi 82342342 - Marco Verdi 342342342'
m = re.search('Mario[a-zA-Z0-9 ]*', elenco)
if m:
print("trovato: " + m.group())
else:
print("not trovato")
trovato: Mario Bianchi 82342342
import re
elenco='Luca Rossi 2345234 - Mario Bianchi 82342342 - Marco Verdi 342342342'
m = re.search('(Mario) ([A-Za-z]*) ([0-9]*)', elenco)
if m:
print("trovato")
print("nome: " + m.group(1))
print("cognome: " + m.group(2))
print("telefono: " + m.group(3))
else:
print("not trovato")
m = re.search('(Mario) ([A-Za-z]*) ([0-9]*)', elenco)
----- --------- ------
m.group(1) m.group(2) m.group(3)
m.group() è tutto
uguale a m.group(0)
Luca Rossi 2345234 - Mario Bianchi 82342342 - Marco Verdi 342342342
----- ------- --------
| | |
(Mario) ([A-Za-z]*) ([0-9]*)
la ricerca ha successo:
Luca Rossi 2345234 - Mario Bianchi 82342342 - Marco Verdi 342342342
----- ------- --------
↑ ↑ ↑ ↑ ↑
| +-+ | +-+ |
| | | | |
-------|-----------|--------
(Mario) ([A-Za-z]*) ([0-9]*)
gli spazi sono caratteri come gli altri
spazio nell'espressione regolare → spazio nella stringa
re.search() trova solo il primo
re.finditer() li trova tutti
import re
elenco='Luca Rossi 2345234 - Mario Bianchi 82342342 - Marco Verdi 342342342'
i = re.finditer('(M[a-z]*) ([A-Za-z]*) ([0-9]*)', elenco)
for m in i:
print('nome: ' + m.group(1) + ' ' \
'cognome: ' + m.group(2) + ' ' \
'telefono: ' + m.group(3))
nome: Mario cognome: Bianchi telefono: 82342342 nome: Marco cognome: Verdi telefono: 342342342
cercare tutte le persone che hanno il primo nome che inizia con M
e il cognome che inizia con Bi oppure Bo
import re
elenco='Luca Rossi 2345234 - ' \
'Mario Bianchi 82342342 - ' \
'Marco Verdi 342342342 - ' \
'Roberto Biscardi 3243456 - ' \
'Bianca Bugatti 343425 - ' \
'Massimo Bologna 343245 - ' \
'Giorgio Mona 3423424 - '
i = re.finditer('(M[a-z]*) (B[io][a-z]*) ([0-9]*)', elenco)
for m in i:
print(m.group())
print(' nome: ' + m.group(1))
print(' cognome: ' + m.group(2))
print(' telefono: ' + m.group(3))
il cognome viene trovato da B[io][a-z]*:
sia intervalli che caratteri elencati uno per uno
sia intervalli che singoli caratteri
trovare solo le persone il cui nome termina con o
import re
…
i = re.finditer('(M[a-z]*o) (B[io][a-z]*) ([0-9]*)', elenco)
…
nome M[a-z]*o
import re
elenco='Luca Rossi 2345234 - ' \
'Mario Bianchi 82342342 - ' \
'Marco Verdi 342342342 - ' \
'Roberto Biscardi 3243456 - ' \
'Bianca Bugatti 343425 - ' \
'Massimo Bologna Morelli 343245 - ' \
'Giorgio Mona 3423424 - ' \
'Maria Bissa 3234543'
i = re.finditer('(M[a-z]*o) (B[io][a-z]*) ([0-9]*)', elenco)
…
non stampa Massimo Bologna Morelli
Massimo Bologna Morelli 343245
------- ------- -
| | |
M[a-z]*o | [0-9]*
B[io][a-z]*
il cognome è tutto Bologna Morelli
incluso lo spazio
e la M maiuscola
import re
elenco='Luca Rossi 2345234 - ' \
…
'Massimo Bologna Morelli 343245 - ' \
…
i = re.finditer('(M[a-z]*o) (B[io][A-Za-z ]*) ([0-9]*)', elenco)
…
anche spazio e lettera maiuscola successiva nel cognome
Massimo Bologna Morelli 343245
------- --------------- ------
| | |
M[a-z]*o | [0-9]*
B[io][A-Za-z ]*
Bologna Morelli collima con B[io][A-Za-z ]*
B o l o g n a M o r e l l i
| | ------------------------
B | |
[io] |
[A-Za-z ]*
abc?
collima con ab e con abc
a seguito da b, eventualmente seguito da c
? = la parte precedente può esserci o meno
import re
elenco='Luca Rossi 2345234 - ' \
…
'Massimo Bologna Morelli 343245 - ' \
…
i = re.finditer('(M[a-z]*o) (B[io][A-Za-z]*( [A-Z][a-z]*)?) ([0-9]*)', elenco)
…
Massimo Bologna Morelli 343245
| | | |
M[a-z]*o | | [0-9]*
B[io][A-Za-z]* |
( [A-Z][a-z]*)?
" Morelli" collima con ( [A-Z][a-z]*)
spazio collima con spazio
M collima con [A-Z]
orelli collima con [a-z]*
Mario Bianchi 82342342
| | '' |
M[a-z]*o | | [0-9]*
B[io][A-Za-z]* |
( [A-Z][a-z]*)?
( [A-Z][a-z]*) è seguita da ?
può anche non esserci
collima con la stringa vuota ''
i = re.finditer('(M[a-z]*o) (B[io][A-Za-z]*( [A-Z][a-z]*)?) ([0-9]*)', elenco)
for m in i:
print(m.group())
print(' nome: ' + m.group(1))
print(' cognome: ' + m.group(2))
print(' telefono: ' + m.group(4)) # quarto gruppo, non terzo
come si conteggiano i gruppi?
(M[a-z]*o) (B[io][A-Za-z]*( [A-Z][a-z]*)?) ([0-9]*)
---------- ------------------------------- --------
gruppo 1 gruppo 2 --------------- gruppo 4
gruppo 3
anche i gruppi dentro i gruppi vengono contati
il telefono ora è il quarto
se manca la parte opzionale, il gruppo 3 è None
elenco='Luca Rossi 2345234 - ' \
'Mario Bianchi 82342342 - ' \
'Marco Verdi 342342342 - ' \
'Roberto Biscardi 3243456 - ' \
'Bianca Bugatti 343425 - ' \
'Massimo Bologna Morelli 343245 - ' \
'Mirko Bosu Scinsani Basini 3435445 - ' \
'Giorgio Mona 3423424 - ' \
'Maria Bissa 3234543'
da uno a tre cognomi
import re
elenco='Luca Rossi 2345234 - ' \
'Mario Bianchi 82342342 - ' \
'Marco Verdi 342342342 - ' \
'Roberto Biscardi 3243456 - ' \
'Bianca Bugatti 343425 - ' \
'Massimo Bologna Morelli 343245 - ' \
'Mirko Bosu Scinsani Basini 3435445 - ' \
'Giorgio Mona 3423424 - ' \
'Maria Bissa 3234543'
i = re.finditer('(M[a-z]*o) (B[io][A-Za-z]*( [A-Z][a-z]*)?( [A-Z][a-z]*)?) ([0-9]*)', elenco)
for m in i:
print(m.group())
print(' nome: ' + m.group(1))
print(' cognome: ' + m.group(2))
print(' telefono: ' + m.group(5)) # quinto gruppo
un cognome
seguito da due, opzionali
(M[a-z]*o) (B[io][A-Za-z]*( [A-Z][a-z]*)?( [A-Z][a-z]*)?) ([0-9]*)
---------- ---------------------------------------------- --------
gruppo 1 gruppo 2 --------------- -------------- gruppo 5
gruppo 3 gruppo 4
anche i gruppi nei gruppi vanno contati
c{2,5} = sequenza, da due a cinque c
import re
elenco='Luca Rossi 2345234 - ' \
'Mario Bianchi 82342342 - ' \
'Marco Verdi 342342342 - ' \
'Roberto Biscardi 3243456 - ' \
'Bianca Bugatti 343425 - ' \
'Massimo Bologna Morelli 343245 - ' \
'Mirko Bosu Scinsani Basini 3435445 - ' \
'Giorgio Mona 3423424 - ' \
'Maria Bissa 3234543'
i = re.finditer('(M[a-z]*o) (B[io][A-Za-z]*( [A-Z][a-z]*){0,2}) ([0-9]*)', elenco)
…
i = re.finditer('(M[a-z]*o) (B[io][A-Za-z]*( [A-Z][a-z]*){0,2}) ([0-9]*)', elenco)
for m in i:
print(m.group())
print(' nome: ' + m.group(1))
print(' cognome: ' + m.group(2))
print(' telefono: ' + m.group(4)) # quarto gruppo, non terzo
basta contare il numero di parentesi aperte
(M[a-z]*o) (B[io][A-Za-z]*( [A-Z][a-z]*){0,2}) ([0-9]*)
---------- ----------------------------------- --------
gruppo 1 gruppo 2 ------------------- gruppo 4
gruppo 3
conteggio parentesi
nel gruppo 3 va solo l'ultima ripetizione di ( [A-Z][a-z]*)
esempio: Mirko Bosu Scinsani Basini 3435445:
la sottoespressione collima con Scinsani Basini
solo Basini va nel gruppo 3
import re
file = open("elenco.txt")
elenco = file.read()
i = re.finditer('(M[a-z]*o) (B[io][A-Za-z]*( [A-Z][a-z]*){0,2}) ([0-9]*)', elenco)
for m in i:
print(m.group())
print(' nome: ' + m.group(1))
print(' cognome: ' + m.group(2))
print(' telefono: ' + m.group(4))
stesso programma
elenco telefonico letto da file di testo
stampare le date nel file testo.txt
le date sono nel formato 21/11/2013
due cifre, barra, due cifre, barra, quattro cifre
[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]
import re
s = open('testo.txt').read()
i = re.finditer('[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]', s)
for m in i:
print(m.group())
non trova 3/1/2012
[0-9]*/[0-9]*/[0-9][0-9][0-9][0-9]
trova 3/1/2012
ma anche 1000/2000/3000
[0-9]{1,2}/[0-9]{1,2}/[0-9]{4,4}
[0-9]{1,2} = una o due cifre
[0-9]{4,4} = quattro cifre
{4,4} si può anche scrivere {4}
invece: [0-9]* era una sequenza di cifre di lunghezza qualsiasi (anche zero)
12/03/2002
-- -- ----
↑ ↑ ↑
+------+ | +---+
| | |
---------- ---------- --------
[0-9]{1,2}/[0-9]{1,2}/[0-9]{4}
12 è [0-9] ripetuto due volte
3/1/2012
- - ----
↑ ↑ ↑
+--------+ | +----+
| | |
---------- ---------- --------
[0-9]{1,2}/[0-9]{1,2}/[0-9]{4}
3 è [0-9] ripetuto una volta
stampare i codici fiscali nel file fiscali.txt
espressione='[A-Z]{3} [A-Z]{3} [0-9]{2}[A-Z][0-9]{2} [A-Z][0-9]{3}[A-Z]'
import re
espressione='[A-Z]{3} [A-Z]{3} [0-9]{2}[A-Z][0-9]{2} [A-Z][0-9]{3}[A-Z]'
s = open('fiscali.txt').read()
i = re.finditer(espressione, s)
for m in i:
print(m.group())
non trova LHTRFG54T32I123N
codice fiscale scritto senza spazi
spazio opzionale: [ ]{0,1}
[A-Z]{3}[ ]{0,1}[A-Z]{3}…
[ ] contiene un singolo carattere
le quadre non servono
[A-Z]{3} {0,1}[A-Z]{3}…
↑
(spazio)
[A-Z]{3} {0,1}[A-Z]{3} {0,1}[0-9]{2}[A-Z][0-9]{2} {0,1}[A-Z][0-9]{3}[A-Z]
{0,1} è uguale a ?
spazio opzionale:
[A-Z]{3} ?[A-Z]{3}…
↑
(spazio)
ancora non si riesce a trovare l'ultimo codice fiscale:
un codice fiscale puo' venire per caso spezzato da un ritorno a capo, come DRT HAR 21S34 C243X
ritorno a capo invece di uno spazio
è un singolo carattere
in molti linguaggi di programmazione: \n
si può inserire in una stringa qualsiasi
a = 'una stringa che contiene\nun ritorno a capo' print(a)
una stringa che contiene un ritorno a capo
n = lettera enne
\n = ritorno a capo
[A-Z]{3}[ \n]?[A-Z]{3}[ \n]?[0-9]{2}[A-Z][0-9]{2}[ \n]?[A-Z][0-9]{3}[A-Z]
ritorno a capo \n
in alternativa allo spazio [ \n]
sempre opzionale ?
[A-Z]{3}.[A-Z]{3}.[0-9]{2}[A-Z][0-9]{2}.[A-Z][0-9]{3}[A-Z]
il punto è un carattere qualsiasi
invece dello spazio o del ritorno a capo
non trova il codice fiscale su due linee
import re
espressione='[A-Z]{3}.[A-Z]{3}.[0-9]{2}[A-Z][0-9]{2}.[A-Z][0-9]{3}[A-Z]'
s = open('fiscali.txt').read()
i = re.finditer(espressione, s, re.DOTALL)
for m in i:
print(m.group())
normalmente, il punto non include il ritorno a capo
con re.DOTALL lo include
21 gennaio 2013 4 luglio 2002 14 agosto 2014
una o due cifre, un nome di mese, quattro cifre
impossibile con le cose viste finora
[0-9]{1,2} [gennaiofebbraiomarzoaprile…] [0-9]{4}
non funziona
è un carattere fra g, e, n, a, ecc.
[0-9]{1,2} [gennaiofebbraiomarzoaprile…]* [0-9]{4}
non funziona
è una sequenza di caratteri qualsiasi fra quelli
prende anche 2 per 1000
gennaio|febbraio|marzo|aprile
alternativa tra stringhe intere
accetta:
gennaio febbraio marzo aprile
[0-9]{1,2} (gennaio|febbraio|marzo|aprile|maggio|giugno|luglio|agosto|settembre|ottobre|novembre|dicembre) [0-9]{4}
parentesi: altrimenti sarebbe una scelta fra:
[abc] è uguale a (a|b|c)
le classi […] si possono usare solo per i singoli caratteri
sono una forma limitata di alternativa
vantaggio: più brevi; permettono a-z ecc.
espressione|espressione|espressione
le espressioni possono essere qualsiasi
[0-9]*|[a-z]*
una sequenza di sole cifre oppure una sequenza di sole minuscole
due formati per la data:
invece: 02/dicembre/2013 non è ammesso
sono due formati alternativi
[0-9]{2}/[0-9]{2}/[0-9]{4}|[0-9]{1,2} (gennaio|febbraio|…) [0-9]{4}
è una alternativa tra due espressioni regolari:
[0-9]{2}/[0-9]{2}/[0-9]{4}
[0-9]{1,2} (gennaio|febbraio|…) [0-9]{4}
dato che [A-Z]{3} si ripete due volte:
([A-Z]{3} ){2}[0-9]{2}[A-Z][0-9]{2} [A-Z][0-9]{3}[A-Z]
l'intera espressione regolare ([A-Z]{3} ) ripetuta due volte
trovare i numeri in numeri.txt
import re
espressione='[0-9]*'
s = open('numeri.txt').read()
i = re.finditer(espressione, s)
for m in i:
print('numero:', m.group())
stampa:
numero: numero: numero: numero: … numero: 234 numero: numero: numero: …
[0-9]* collima anche con la stringa vuota
[0-9][0-9]*
prima una cifra
poi una cifra ripetuta un numero qualsiasi di volte
[0-9]{1,}
secondo numero assente in {1,}
uguale qualsiasi
[0-9]+
+ = numero qualsiasi di volte tranne zero
* è uguale a {0,}
da zero a qualsiasi ripetizioni
+ è uguale a {1,}
da uno a qualsiasi ripetizioni
stampare le somme
somma: intero+intero
solo due interi, per ora
un intero: [0-9]+
una somma tra due interi: [0-9]{1,}[+][0-9]{1,}
il carattere di somma va tra quadre
altrimenti è la ripetizione da una a qualsiasi volte
anche somme di tre interi
[0-9]{1,}[+][0-9]{1,}
--------- ---------
intero + intero
la sequenza +intero va ripetuta
almeno una volta
[0-9]{1,}([+][0-9]{1,})+
--------- ------------
intero +intero
---------------
+intero+intero+intero...
somme, sottrazioni, moltiplicazioni, divisioni
anche mescolate fra loro
[0-9]{1,}([+-*/][0-9]{1,})+
vari errori
+-*/ significa alternativa fra
[0-9]{1,}([+*/-][0-9]{1,})+
subito prima della quadra chiusa
il trattino è il carattere trattino
tutti applicabili a espressioni complesse tranne […]
trovare nomi come elenco.txt o numeri.txt
dove vanno cercati: filetesto.txt
il file elenco.txt contiene un primo esempio mentre testo.txt, fiscali.txt e numeri.txt sono altri esempi
estensione di elenco.txt:
solo la parte finale txt
.*[.]txt
sequenza che termina con .txt
file: il file elenco.txt contiene un primo esempio mentre testo.txt, fiscali.txt file: numeri.txt
più corta:
il file elenco.txt contiene un primo esempio mentre testo.txt, fiscali.txt e
| |
--------------|txt
.* |
[.]
più lunga:
il file elenco.txt contiene un primo esempio mentre testo.txt, fiscali.txt e
| | |
----------------------------------------------------------------------|txt
.* |
[.]
intermedia:
il file elenco.txt contiene un primo esempio mentre testo.txt, fiscali.txt e
| |
---------------------------------------------------------|txt
.* |
[.]
viene sempre scelta la collimazione più lunga
[^ \n]*[.]txt
il nome del file non include lo spazio
e nemmeno il ritorno a capo
file: elenco.txt file: testo.txt file: fiscali.txt file: numeri.txt
vengono considerate diverse:
if re.search('a', 'rsAmoe'):
print 'trovato'
non trova niente, invece:
if re.search('a', 'rsAmoe', re.IGNORECASE):
print 'trovato'
trova la maiuscola
non era per re.DOTALL?
si possono anche mettere tutti e due:
if re.search('a', 'fsAsdf', re.DOTALL | re.IGNORECASE):
print 'trovato'
l'operatore | è l'OPPURE sui singoli bit
sistema molto usato per passare più opzioni:
print('re.DOTALL:', re.DOTALL+1-1)
print('re.IGNORECASE:', re.IGNORECASE+1-1)
numeri 16 e 2
re.DOTALL|re.IGNORECASE
16 = 10000 2 = 00010 16|2 = 10010 = 18
terzo argomento flags
default: flags=0
flags&re.DOTALL= 00000 & 00010
non include \n nel .
se flags=re.DOTALL|re.IGNORECASE:
flags&re.DOTALL = 10010 & 00010
re.DOTALL|re.IGNORECASE = 10000 | 00010 = 10010
& 00010
| aggiunge un bit
& seleziona solo quello
re.search(espressione, stringa) re.finditer(espressione, stringa)
trovano una slice all'interno della stringa
può essere all'inizio, in mezzo o in fondo
si può specificare che deve essere all'inizio o alla fine
esempio:
re.search('a', 'casupola') ha successo
re.search('^a', 'casupola') no
(la a c'è ma non all'inizio)
come ^, ma con $
m=re.search('a+$', 'aaa bb ccc aaxaa zz aaaaa')
print m.group()
trova solo la sequenza di a in fondo
i=re.finditer('^a', 'aaaanbb sdaaaa aaa')
for m in i:
print m.group()
stampa solo a
ci sono altre a, ma non all'inizio
es: nome
import re
m = re.search('^[A-Z][a-z]+$', s)
if m:
print 'nome'
ha successo solo se il nome è tutta la stringa s
trovare tutti gli articoli 'il' in testo.txt
import re
s = open('testo.txt').read()
print("espressione 'il':")
i = re.finditer('il', s)
for m in i:
print(m.group())
risultato:
espressione 'il': il il il
trova anche 'il' in 'possibile'
include anche gli spazi
import re
s = open('testo.txt').read()
print("espressione ' il ':")
i = re.finditer(' il ', s)
for m in i:
print(m.group())
risultato:
espressione ' il ': il
non trova 'il' all'inizio della riga
include anche gli spazi
import re
s = open('testo.txt').read()
print("espressione r'\\bil\\b':")
i = re.finditer(r'\bil\b', s)
for m in i:
print(m.group())
risultato:
espressione r'\bil\b': il il
import re
s = open('testo.txt').read()
print("espressione r'\\bil\\b':")
i = re.finditer(r'\bil\b', s)
for m in i:
print(m.group())
risultato:
espressione r'\bil\b': il il
\b collima solo con inizio e fine di parola
spazio, inizio o fine riga
lo spazio prima della parola non va nel gruppo
nemmeno quello dopo
devono esserci, ma non vengono "consumati"
senza r la \b sarebbe
un carattere speciale
invece del delimitatore di parola
^ e $ sono nell'espressione regolare
richiedono la presenza di qualcosa nella stringa (inizio e fine)
ma non vanno nel gruppo
\b inizio o fine di una parola
richiede che ci sia prima un inizio di stringa o uno spazio
ma non va nel gruppo
includere anche la parola dopo 'il'
import re
s = open('testo.txt').read()
print("espressione r'\\bil\\b':")
i = re.finditer(r'\bil\b[a-z0-9]*', s)
for m in i:
print(m.group())
risultato:
espressione r'\bil\b[a-z0-9]*': il il
non trova la parola
import re
s = open('testo.txt').read()
print("espressione r'\\bil\\b':")
i = re.finditer(r'\bil\b[a-z0-9]*', s)
for m in i:
print(m.group())
risultato:
espressione r'\bil\b[a-z0-9]*': il il
\bil\b collima con 'il'
non con ' il '
c'è ancora uno spazio, prima delle cifre
import re
s = open('testo.txt').read()
print("espressione r'\\bil\\b':")
i = re.finditer(r'\bil\b [a-z0-9]*', s)
for m in i:
print(m.group())
risultato:
espressione r'\bil\b [a-z0-9*': il giorno il 3
\bil\b collima con 'il'
segue uno spazio
segue la parola successiva
divide una stringa in parti
l'espressione regolare dice dove separare
es: [;|] dice che ; e | fungono da separatori
p = re.compile('[;|]')
print p.split('abcd;efgh|wsl')
stampa:
['abcd', 'efgh', 'wsl']
rimpiazza le sottostringhe che collimano con l'espressione regolare
p = re.compile('(Giorgio|Luca|Alberto)')
print p.sub('Gianni', "Questo l'ha fatto Giorgio, questo Alberto, questo Luca")
stampa:
Questo l'ha fatto Gianni, questo Gianni, questo Gianni
esempio:
sed 's/^\([a-z]*\)-\([a-z]*\)/\2-\1/'
rimpiazza abcd-xyz con xyz-abcd
\(…\) indicano i gruppi
nel rimpiazzamento \2-\1, i numeri \2 e \1 indicano i gruppi nella stringa
command.com in DOS e Windows
(prompt dei comandi)
/bin/bash e simili in UNIX
usano forme limitate di espressioni regolari
ls a* (bash) dir a*.* (command)
si usa * al posto di .*
indica una ripetizione di caratteri qualsiasi
visualizza in nomi dei file che iniziano con a
esempio: google docs
all'interno di una pagina html5:
<input type="text" title="una data"
pattern="[0-9]{1,2}/[0-9]{1,2}/[0-9]{4}" />
effetto:
tab o pulsante prova:
verifica che nel campo ci sia una data
modello matematico
si guarda l'intera stringa
come ^espressione$
se l'alfabeto è A:
An è l'insieme di tutte le stringhe di lunghezza n fatte di simboli di A
A* è l'insieme di tutte le stringhe fatte di simboli di A
una espressione regolare è un modo per specificare un insieme di stringhe
dato un alfabeto A, una espressione regolare lo divide in:
dato un alfabeto:
nella trattazione teorica:
ε indica la stringa vuota
esempio:
ε|e = e?
? si può definire in termini di ε |
espressione regolare → insieme di stringhe che collimano
la semantica è una funzione matematica collimano()
data una espressione regolare e:
collimano(e) = insieme di stringhe che collimano con l'espressione regolare
definizione generale di collimano?
definire collimano per ogni espressione regolare
modo "automatico" per dire quanto vale collimano(e)
sistema: seguire la definizione sintattica
la sintassi era:
una espressione regolare è: un carattere, oppure ε, oppure …
vari casi
definire collimano in ognuno
| possibile espressione regolare | semantica |
|---|---|
| ε | collima(ε)=? |
| x ∈ alfabeto | collima(x)=? |
| ef | collima(ef)=? |
| e* | collima(e*)=? |
| e|f | collima(e|f)=? |
| e? | collima(e?)=? |
in ognuno dei casi, definire collima
deve produrre le stringhe che collimano
l'unica stringa che collima con ε è la stringa vuota
collima(ε)={∅}
l'unica stringa che collima con l'espressione regolare x è la stringa composta solo dal carattere x
collima(x)={x}
se è una concatenazione di caratteri:
collima(xy)={xy}
in generale?
es: a*b? è la concatenazione di a* e
b?
cosa c'è in collima(a*b?)?
problema: definire collima(a*b?)
ma a* è una espressione regolare
anche b?
quindi collima sarà definito anche per loro
a prima vista: collima è definito in termini di se stesso
problema dell'uovo e della gallina
in realtà no
non in questo caso
gallina → uovo → gallina → uovo → …
il problema è che da gallina si torna a gallina
con le espressioni regolari no!
collima(a*b?) → collima(a*) collima(b?)
↓ ↓
collima(a) collima(b)
non ci sono cicli
collima è definito in termini di se stesso?
non esattamente:
collima(e) è definito in termini di collima(f), collima(g), ecc. dove f e g sono più semplici di e
es. ef definito in termini di e e di f
e* definito in termini di e, ecc.
collima(e) è definito in termini di collima(f)
ecc.,
più semplici
collima(f) è definito in termini di collima(g),
ecc.
ancora più semplici
ecc.
da collima(e) prima o poi si arriva a collima(ε) e collima(x)