39
Python Standard Library Espressioni Regolari

Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Python Standard LibraryEspressioni Regolari

Page 2: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Espressioni Regolari

› Un'espressione regolare (regular expression o regex) è una sequenza di caratteri che identifica un insieme di stringhe.

› Sono un potente strumento che consente di trovare, estrarre e sostituire parti di testo all'interno di un documento.

› Benché siano state formalizzate dal punto di vista puramente matematico fin dagli anni quaranta, è con l'avvento dei sistemi UNIX che comparirono i primi tool basati sulle espressioni regolari (tra cui un precursore dell'attuale grep).

Page 3: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Esempi di regex

[-+]?[0-9]+

Trova tutti i numeri interi con segno.

^.*\.txt$

Trova tutti i file che hanno estensione txt.

\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}

Trova gli indirizzi IPv4.

^4[0-9]{12}(?:[0-9]{3})?$

Trova numeri di carte di credito.

Page 4: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Le regex più semplici

› Nella loro forma più semplice, una regex è una sequenza di caratteri alfanumerici.

› abc ad esempio, trova la stringa 'abc'.

› Le espressioni regolari, di norma, sono case sensitive. La regex di prima infatti troverà la stringa 'abc', ma non la stringa 'Abc' o 'aBc'.

› Le regex possono, tramite regole opportune, trovare qualsiasi carattere, compresi gli altri caratteri ASCII ('~', '|') e persino quelli Unicode ('è', '①', '⼦').

› Bisogna tuttavia porre attenzione al fatto che alcuni caratteri hanno una funzione particolare nel linguaggio delle regex.

Page 5: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Notazione

› Le espressioni regolari saranno sempre indicate in carattere monospaced.

› Per indicare che una regex trova un determinato insieme di stringhe verrà utilizzato il simbolo →.

› L'insieme di stringhe trovate da una regexseguono la consueta notazione insiemistica. Un insieme illimitato è delimitato dai puntini di sospensione.

abc → {'abc'}

Page 6: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Quantificatore *

*

Detto anche stella di Kleene, serve per trovare famiglie di stringhe che hanno da 0 a N ripetizioni di uno stesso carattere.

ab*c → {'ac', 'abc', 'abbc', 'abbbc', …}

I quantificatori si riferiscono sempre al carattere immediatamente precedente.

Page 7: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Quantificatori + e ?

+

Identico a *, ma le ripetizioni ammesse sono da 1 a N, e non da 0 a N.

ab+c → {'abc', 'abbc', 'abbbc', …}

?

Ammette l'opzionalità del carattere precedente (può essere presente 0 o 1 volta).

ab?c → {'ac', 'abc'}

Page 8: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Operatore \

\

Effettua l'escaping del carattere precedente, se esso è un carattere particolare.

a** → Non valida

a\** → {'a', 'a*', 'a**', 'a***', …}

a*\* → {'*', 'a*', 'aa*', 'aaa*', …}

a\*\* → {'a**'}

a\c → Non valida

a\\c → {'a\c'}

Page 9: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Gruppi

› In realtà non è vero che gli operatori si applicano al carattere precedente: è più corretto dire che si applicano al token precedente.

› Un token, nel caso più semplice, è un carattere, ma può essere anche un gruppo o una classe di caratteri.

› In particolare, un gruppo di caratteri è una stringa delimitata dalle parentesi tonde.

a(bc)*d → {'ad', 'abcd', 'abcbcd', …}

› Nell'esempio precedente, il token su cui è applicata la stella di Kleene è (bc).

› L'ordine dei caratteri all'interno del gruppo è importante!

a(cb)*d → {'ad', 'acbd', 'acbcbd', …}

Page 10: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Operatore|

Specifica alternative all'interno di un gruppo.

gr(a|e)y → {'gray', 'grey'}

In un gruppo possono essere presenti più alternative in qualsiasi ordine, e le alternative sono stringhe di qualsiasi lunghezza.

(cla|repl|gu)y → {'clay', 'reply', 'guy'}

È inoltre possibile specificare la stringa vuota come alternativa:

(na|)y → {'y', 'nay'}

Page 11: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Classi

› Esiste un modo più pratico per trovare alternative di singoli caratteri, ossia definire una classe di caratteri.

› Una classe di caratteri è un insieme non ordinato di caratteri in alternativa tra di loro delimitato da parentesi quadre.

› La regular expression gr(a|e)y può essere dunque riscritta come:

gr[ae]y → {'gray', 'grey'}

Page 12: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Classi

› I quantificatori visti finora perdono di significato se sono inseriti all'interno di una classe, eccetto l'operatore \.

a[-+*\\]b → {'a+b', 'a-b', 'a*b', 'a\b'}

› Una classe di caratteri è anche essa un token su cui è possibile applicare un quantificatore.

a[cd]?b → {'ab', 'acb', 'adb'}

› Lo spazio è un carattere ammesso.

a[ _]b → {'a_b', 'a b'}

Page 13: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Intervalli

Il carattere - definisce un intervallo di caratteri all'interno di una classe.

Esso è utilizzabile solamente per definire intervalli di caratteri alfanumerici, sia uppercase che lowercase: se usato singolarmente si comporta come un normale carattere.

1[0-4] → {'10', '11' , '12' , '13' , '14'}

[A-Za-z]* → una qualsiasi sequenza di lettere

[+-]?17 → {'17', '+17' , '-17'}

Page 14: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Negazione

Il carattere ^, se posto all'inizio di una classe, specifica che la classe rappresenta i caratteri che NON devono essere presenti.

Perde questo significato se è non è il primo carattere di una classe.

1[^0-4] → {'15', '16' , '1a' , '1T' , …}

a[&^|]b → {'a&b', 'a^b' , 'a|b'}

Page 15: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Classi speciali

.

Trova qualsiasi carattere eccetto il newline '\n'.

. → {'a', 'b' , '4' , '&' , …}

\d

Trova caratteri numerici. Include [0-9] ma anche tutti i caratteri non-ASCII riconducibili a numeri.

\d → {'0', '1' , '2' , '3' , '𝟘', …}

Page 16: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Classi speciali

\s

Trova whitespace. Include [ \t\n\r\f\v] e tutti i caratteri whitespace speciali Unicode.

\w

Trova caratteri alfanumerici. Include [A-Za-z0-9_] ma anche tutti i caratteri non-ASCII riconducibili a numeri o lettere.

\w → {'a', 'T' , '9' , 'è' , '①', '_', …}

Page 17: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Classi speciali

› Esistono anche le classi duali di \d, \w, e \s, e sono rispettivamente \D, \W, \S.

› Esse trovano esattamente i caratteri complementari alle classi base:– \D trova tutti i caratteri che non sono numeri.

– \W trova tutti i caratteri che non sono numeri né lettere.

– \S trova tutti i caratteri non whitespace.

\W → {'#', '[' , '+' , '.' , '€', …}

Page 18: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Classi speciali

› Le classi speciali \d, \w, e \s, e le loro duali possono essere utilizzate all'interno di altre classi.

[\daB] → {'0', '1' , '2' , … , 'a', 'B'}

› Il punto all'interno di una classe invece vale sempre e solo come carattere, non come classe.

[^.] → tutti i caratteri tranne '.'

Page 19: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Quantificatori greedy e lazy

› Di norma, i quantificatori sono sempre greedy, ossia cercano di trovare quanti più caratteri possibili.

› A volte questo comportamento non è quello desiderato.

› Immaginiamo di volere estrarre il nome del tag dal seguente frammento di HTML:

<div>Some paragraph</div>

Page 20: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Quantificatori greedy e lazy

<div>Some paragraph</div>

Regex pattern: <.*>

› Sappiamo che il punto trova qualsiasi carattere eccetto il newline.

› Il problema è che anche '>' è un carattere! È quindi perfettamente logico che venga incluso nella stringa trovata.

Page 21: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Quantificatori greedy e lazy

› La soluzione al problema è rendere il quantificatore lazy, facendogli catturare la minorquantità di caratteri possibili che soddisfano l'espressione regolare.

› Per specificare che un quantificatore è lazy si usa il punto interrogativo.

<div>Some paragraph</div>

Regex pattern: <.*?>

Page 22: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Ancore

› Quando si ricerca una pattern all'interno di una stringa, a volte è utile specificare esplicitamente dove questa pattern deve essere collocata all'interno del testo.

hear ya, hear ya

Regex pattern: hear

› Esistono degli operatori, chiamati ancore (anchors), che vincolano la posizione delle sequenze di caratteri trovate.

Page 23: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Ancore

^

Vincola la posizione della sequenza di caratteri trovata all'inizio della stringa.

hear ya, hear ya

Regex pattern: ^hear

$

Vincola la posizione della sequenza di caratteri trovata alla fine della stringa.

hear ya, hear ya

Regex pattern: ya$

Page 24: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Modulo re

https://docs.python.org/3/library/re.html

Python permette, tramite il suo modulo re, di utilizzare il motore delle espressioni regolari.

Page 25: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

re.search

re.search(pattern, string, flags=0)

Cerca in string la pattern regex specificata.

flags è un intero che modifica il comportamento della funzione.

Il suo valore di ritorno è un Match object.

>>> html = '<div>Another paragraph</div>'

>>> re.search('<.*?>', html)

<_sre.SRE_Match object at 0x1ab06a0>

Page 26: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Match object

Contengono varie informazioni sulle stringhe trovate.

Sono convertibili automaticamente al booleano True:

match = re.search(pattern, string)

if match:

process(match)

I match object possono essere usati per accederealle stringhe trovate corrispondenti ai vari gruppi.

Page 27: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

match.group

match.group([group1, …])

Restituisce una o più stringhe trovate corrispondenti a uno o più gruppi.

Chiamata senza argomenti è equivalente a chiamare match.group(0).

Se uno dei groupN è 0, il valore corrispondente sarà l'intera stringa trovata.

Se vengono passati più gruppi come parametri, restituisce una tupla contenente tutte le stringhe relative a quei gruppi.

Page 28: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Esempio

>>> import re

>>> text = "Isaac Newton, physicist"

>>> m = re.match(r"(\w+) (\w+)", text)

>>> m.group()

'Isaac Newton'

>>> m.group(1)

'Isaac'

>>> m.group(0, 2)

('Isaac Newton', 'Newton')

Page 29: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Raw strings

› Per evitare di inserire troppi caratteri di escape, in python è possibile dichiarare una stringa come rawstring.

› Le raw string si dichiarano mettendo la lettera rprima della stringa.

>>> r'Hello!\n'

'Hello!\\n'

Page 30: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

match.groups

match.groups(default=None)

Restituisce una tupla contenente tutte le stringhe trovate dai vari gruppi.

default è usato quando un gruppo opzionale non è presente nella stringa d'origine.

>>> import re

>>> m = re.match(r"(\d+)\.?(\d+)?", "24")

>>> m.groups()

('24', None)

>>> m.groups('0')

('24', '0')

Page 31: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

re.sub

re.sub(pattern, repl, string, count=0, flags=0)

Sostituisce in string la pattern regex specificata con la stringa repl fino ad un massimo di count volte.

Se count è 0 sostituisce tutte le occorrenze di pattern con repl.

flags è un intero che modifica il comportamento della funzione.

>>> html = '<div>Another paragraph</div>'

>>> re.sub('(</|<).*?>', r'\1span>', html)

' <span>Another paragraph</span>'

Page 32: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Backreference

La \1 nell'esempio è chiamata backreference.

Viene sostituita durante l'elaborazione con la stringa trovata dalla pattern specificata nel primo gruppo.

\1 assumerà il valore corrispondente alla stringa che viene trovata dalla pattern del primo gruppo.

<div>Another paragraph</div>

Regex pattern: (</|<).*?>

Match: <div> ⇒ \1 = '<'

Match: </div> ⇒ \1 = '</'

Se sono definiti più gruppi, è possibile usare la backreference \i (ove i è un numero) per ricavare ilvalore dell'i-esimo gruppo.

Page 33: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

re.split

re.split(pattern, string, maxsplit=0, flags=0)

Divide string in frammenti usando come divisore pattern, creando al massimo maxsplit frammenti.

Se maxsplit è 0 invece divide la stringa il più possibile.

flags è un intero che modifica il comportamento della funzione.

Restituisce una lista di stringhe corrispondenti ai frammenti.

Page 34: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Esempio

>>> import re

>>> text = 'Words, words, words.'

>>> re.split('\W+', text)

['Words', 'words', 'words', '']

>>> re.split('\W+', text, 1)

['Words', 'words, words.']

Page 35: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Alcune flag

re.DOTALL (re.S)

Il . trova anche i caratteri newline '\n'.

re.MULTILINE (re.M)

La ricerca viene effettuata su ogni linea della stringa, non una volta sola.

re.IGNORECASE (re.I)

Ignora il case delle lettere presenti in pattern.

Page 36: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Alcune flag

re.UNICODE (re.U)

Le classi \w, \d, \s e duali trovano, oltre ai caratteri ASCII corrispondenti, anche eventuali caratteri Unicode equivalenti.

! In python 3 è il comportamento di default, quindi non è necessario specificarlo.

re.ASCII (re.A)

Le classi \w, \d, \s e duali trovano solamente caratteri ASCII.

! In python 2 è il comportamento di default, e questa flag non esiste.

Page 37: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

re.compile

re.compile(pattern, flags=0)

È possibile compilare una pattern in un oggetto regex. Questo è utile se si pensa di riutilizzare la stessa regex pattern più di una volta.

flags ha lo stesso significato dei metodi

Sull'oggetto regex è possibile chiamare i metodi search, sub e split.

>>> import re

>>> regex = re.compile(pattern)

>>> regex.search(text)

Page 38: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Esercizio: iwget

› iwget è un'utilità a riga di comando che scarica tutte le immagini di una pagina web.

› Per farlo dobbiamo compiere i seguenti passi:

1. Accettare l'URL della pagina web da riga di comando.

2. Scaricare la pagina (X)HTML corrispondente all'URL.

3. Leggere il contenuto di tutti gli attributi src delle tag img, tenendo presente che l'(X)HTML non sempre è ben formato.

4. Per ogni match, scaricare l'immagine in una qualsiasi cartella locale.

Page 39: Espressioni Regolari - UniCT · In python 3 è il comportamento di default, quindi non è necessario specificarlo. re.ASCII(re.A) Le classi \w, \d, \s e duali trovano solamente caratteri

Esercizio: iwget

› Per svolgere questo esercizio abbiamo bisogno di una libreria che consente di scaricare pagine web.

› Non è tuttavia parte del corso spiegare come utilizzarla.

› La soluzione? Documentazione ufficiale!