Salta ai contenuti
Manuale LogoManuale Logo

Espressioni regolari

Per controllare un indirizzo email o trovare numeri di telefono in un testo, potresti scrivere molte condizioni if. Le espressioni regolari descrivono questi schemi in modo compatto.

Le espressioni regolari (dette anche “regex” o “regexp”) descrivono schemi di testo. Puoi usarle per:

  • Verificare se una stringa corrisponde a un certo formato (“è un’email valida?”)
  • Trovare schemi in un testo (“tutti i numeri in questo paragrafo”)
  • Estrarre informazioni (“dammi solo la data da questa riga”)
  • Sostituire parti di testo (“sostituisci tutti i numeri con X”)

In Python si usano con il modulo re:

import re
Simbolo Significato Esempio
. Qualsiasi carattere (eccetto a capo) a.c trova “abc”, “aXc”, “a3c”…
\d Una cifra (0-9) \d\d trova “42”, “07”…
\D Non una cifra
\w Lettera, cifra o underscore
\s Spazio, tab o a capo
^ Inizio della stringa ^Ciao trova solo stringhe che iniziano con “Ciao”
$ Fine della stringa fine$ trova solo stringhe che terminano con “fine”
[abc] Uno tra a, b, c
[a-z] Una lettera minuscola qualsiasi
[0-9] Una cifra qualsiasi (come \d)
Simbolo Significato
* Zero o più volte
+ Una o più volte
? Zero o una volta
{3} Esattamente 3 volte
{2,5} Da 2 a 5 volte
import re
testo = "Il mio numero è 334-1234567"
# Schema: 3 cifre, un trattino, 7 cifre
risultato = re.search(r"\d{3}-\d{7}", testo)
if risultato:
print(f"Numero trovato: {risultato.group()}") # → 334-1234567
else:
print("Nessun numero trovato")

Il prefisso r prima delle virgolette (r"...") indica una raw string (stringa “grezza”). Senza r, Python interpreterebbe \d come una sequenza speciale, come \n. Con r, Python lascia il testo invariato. Usa r"..." nelle espressioni regolari.

import re
testo = "Ciao, mondo!"
risultato = re.match(r"Ciao", testo) # La stringa inizia con "Ciao"?
if risultato:
print("Trovato!")
else:
print("Non trovato.")
import re
testo = "Ho 3 mele, 5 banane e 2 arance."
numeri = re.findall(r"\d+", testo) # Trova tutti i gruppi di cifre
print(numeri) # ['3', '5', '2']
import re
testo = "Il prezzo è 10 euro, poi 20 euro."
nuovo = re.sub(r"\d+", "X", testo) # Sostituisce tutti i numeri con "X"
print(nuovo) # Il prezzo è X euro, poi X euro.

Come str.split(), ma puoi dividere su uno schema complesso invece che su un singolo carattere:

import re
testo = "mela; banana, uva ciliegia"
# Divide su punto e virgola, virgola o spazi (anche multipli)
parti = re.split(r"[;,\s]+", testo)
print(parti) # ['mela', 'banana', 'uva', 'ciliegia']

Le parentesi tonde creano dei gruppi e permettono di estrarre separatamente le parti del risultato:

import re
testo = "Data di nascita: 15/03/2008"
match = re.search(r"(\d{2})/(\d{2})/(\d{4})", testo)
if match:
giorno = match.group(1) # Primo gruppo → 15
mese = match.group(2) # Secondo gruppo → 03
anno = match.group(3) # Terzo gruppo → 2008
print(f"Giorno: {giorno}, Mese: {mese}, Anno: {anno}")

Se usi lo stesso schema molte volte, “compilalo” una volta sola:

import re
schema_numeri = re.compile(r"\d+") # Compila lo schema una volta
frasi = ["Ho 3 mele", "Ho 10 banane", "nessun numero qui"]
for frase in frasi:
trovati = schema_numeri.findall(frase)
if trovati:
print(f"Trovati: {trovati}")
import re
def valida_email(email):
# Schema: caratteri@caratteri.dominio (almeno 2 lettere)
schema = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
return bool(re.match(schema, email))
print(valida_email("alice@esempio.it")) # True ← valida
print(valida_email("non_valida.com")) # False ← manca la @
print(valida_email("@dominio.it")) # False ← manca la parte prima della @
import re
def valida_telefono(numero):
# Schema: opzionalmente +39, poi 9 o 10 cifre
schema = r"^(\+39)?[0-9]{9,10}$"
return bool(re.match(schema, numero))
print(valida_telefono("3341234567")) # True
print(valida_telefono("+393341234567")) # True
print(valida_telefono("abc")) # False