Cosa sono le espressioni regolari

Le espressioni regolari (regex o regexp) sono sequenze di caratteri che definiscono un pattern di ricerca. Permettono di cercare, validare, estrarre e sostituire testo con una precisione impossibile con i normali metodi stringa. Sono supportate in tutti i linguaggi di programmazione moderni — JavaScript, Python, Java, PHP, Ruby, Go — con sintassi quasi identica.

Una regex è composta da caratteri letterali (che matchano se stessi) e metacaratteri (che hanno significati speciali). Capire questa distinzione è il primo passo per padroneggiare le regex.

🔧 Regex Builder Visuale
Costruisci e testa espressioni regolari con un'interfaccia visuale. Ogni blocco viene spiegato in italiano e testato in tempo reale.
Usa il tool →

I metacaratteri fondamentali

MetacarattereSignificatoEsempio
.Qualsiasi carattere (tranne newline)a.c → "abc", "axc"
\dCifra (0-9)\d\d → "42", "99"
\DNon cifra\D+ → "abc", "xy"
\wCarattere parola (a-z, A-Z, 0-9, _)\w+ → "hello_123"
\WNon carattere parola\W → " ", "!", "@"
\sSpazio bianco (spazio, tab, newline)\s+ → " "
\SNon spazio bianco\S+ → "testo"
^Inizio stringa (o riga con flag m)^ciao → "ciao mondo"
$Fine stringa (o riga con flag m)mondo$ → "ciao mondo"
\bWord boundary\bcat\b → "cat" ma non "cats"
[abc]Classe di caratteri — uno tra a, b, c[aeiou] → vocali
[^abc]Negazione classe — nessuno tra a, b, c[^0-9] → non cifre
[a-z]Intervallo — da a a z[a-zA-Z] → lettere
\Escape — usa il carattere letteralmente\. → punto letterale

Quantificatori: quante volte deve matchare

QuantificatoreSignificatoLazy (minimo)
*0 o più volte*?
+1 o più volte+?
?0 o 1 volta (opzionale)??
{n}Esattamente n volte
{n,}Almeno n volte{n,}?
{n,m}Da n a m volte{n,m}?

Greedy vs Lazy: la differenza pratica

I quantificatori di default sono greedy: catturano il massimo possibile. Aggiungendo ? diventano lazy: catturano il minimo.

# Input: <b>grassetto</b> e <i>corsivo</i> # Greedy: cattura dal primo < all'ultimo > /<.+>/ → "<b>grassetto</b> e <i>corsivo</i>" # Lazy: cattura ogni tag separatamente /<.+?>/ → "<b>", "</b>", "<i>", "</i>"

Gruppi di cattura e riferimenti

Le parentesi tonde creano gruppi di cattura che puoi estrarre o riutilizzare:

# Gruppo numerato — accessibile come $1, $2 o \1, \2 /(\d{4})-(\d{2})-(\d{2})/ # Match su "2026-04-25": # group 1: "2026" (anno) # group 2: "04" (mese) # group 3: "25" (giorno) # Named group (ES2018+, Python, .NET) — accessibile come groups.nome /(?<anno>\d{4})-(?<mese>\d{2})-(?<giorno>\d{2})/ # Non-capturing group — raggruppa senza catturare /(?:https?|ftp):\/\//

Backreference: riferirsi a un gruppo già catturato

# Trova parole duplicate consecutive /\b(\w+)\s+\1\b/ # Matcha "il il", "the the", "un un" ecc. # In replace: inverte giorno e mese di una data "25/04/2026".replace(/(\d{2})\/(\d{2})\/(\d{4})/, "$2/$1/$3") # → "04/25/2026"

Lookahead e Lookbehind — assertions

Le assertions guardano avanti o indietro senza consumare caratteri — non fanno parte del match ma condizionano cosa viene matchato:

# Lookahead positivo (?=...) — matcha X solo se seguito da Y /\d+(?= euro)/ → "100" in "100 euro" (non in "100 dollari") # Lookahead negativo (?!...) — matcha X solo se NON seguito da Y /\d+(?! euro)/ → "100" in "100 dollari" (non in "100 euro") # Lookbehind positivo (?<=...) — matcha X solo se preceduto da Y /(?<=€)\d+/ → "100" in "€100" # Lookbehind negativo (?<!...) — matcha X solo se NON preceduto da Y /(?<!€)\d+/ → "100" in "$100" (non in "€100")

I flag delle regex

FlagNomeEffetto
gglobalTrova tutti i match (non solo il primo)
iignoreCaseCase-insensitive: "A" matcha "a"
mmultiline^ e $ matchano inizio/fine riga
sdotAllIl punto matcha anche newline (ES2018+)
uunicodeTratta il pattern come Unicode
dhasIndicesAggiunge indici start/end ai match (ES2022+)
🧪 Regex Tester
Testa le tue espressioni regolari in tempo reale con evidenziazione dei match e dei gruppi catturati.
Testa ora →

15 pattern pronti all'uso

Email
/^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/
Validazione base email. Nota: la specifica RFC 5322 è molto più complessa — questa regex copre il 99% dei casi reali.
URL (http e https)
/^https?:\/\/([\w\-]+\.)+[\w\-]{2,}(\/[\w\-._~:/?#[\]@!$&'()*+,;=%]*)?$/
Matcha URL con http o https, dominio e path opzionale.
Codice Fiscale Italiano
/^[A-Z]{6}\d{2}[ABCDEHLMPRST]\d{2}[A-Z]\d{3}[A-Z]$/i
Verifica il formato del codice fiscale (non il checksum). Per validazione completa usa la calcolatrice dedicata.
Partita IVA Italiana
/^\d{11}$/
11 cifre. Per validazione completa del checksum serve logica aggiuntiva non esprimibile con regex.
Numero di telefono italiano
/^(\+39)?[\s\-]?(0\d{1,4}|3\d{2})[\s\-]?\d{5,8}$/
Copre fissi (0xx) e mobili (3xx) con prefisso +39 opzionale e separatori spazio/trattino.
Data formato italiano (GG/MM/AAAA)
/^(0?[1-9]|[12]\d|3[01])\/(0?[1-9]|1[0-2])\/\d{4}$/
Valida giorni 1-31, mesi 1-12, anno 4 cifre. Non verifica la coerenza giorno/mese (es. 31/02).
Data formato ISO (AAAA-MM-GG)
/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/
Formato ISO 8601 standard per database e API.
Numero intero (positivo e negativo)
/^-?\d+$/
Matcha interi positivi e negativi. Modifica in /^\d+$/ per solo positivi.
Numero decimale (virgola o punto)
/^-?\d+([.,]\d+)?$/
Accetta sia 3.14 che 3,14 — utile per form con input italiano.
Password sicura
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/
Almeno 8 caratteri, una minuscola, una maiuscola, una cifra, un carattere speciale.
CAP italiano
/^\d{5}$/
5 cifre esatte. I CAP italiani vanno da 00010 a 98168.
Indirizzo IPv4
/^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/
Valida ogni ottetto da 0 a 255. Matcha "192.168.1.1" ma non "999.0.0.1".
UUID v4
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
Formato UUID versione 4 (random). Il terzo gruppo inizia sempre con 4, il quarto con 8, 9, a o b.
Slug URL
/^[a-z0-9]+(?:-[a-z0-9]+)*$/
Solo minuscole, cifre e trattini. Nessun trattino all'inizio, alla fine o doppio.
Tag HTML
/<([a-zA-Z][a-zA-Z0-9]*)\b[^>]*>.*?<\/\1>/s
Matcha tag apertura e chiusura corrispondenti. Attenzione: non usare per parsing HTML serio — usa un parser DOM.

Errori comuni e come evitarli

Il punto matcha tutto

L'errore più frequente dei principianti: usare . quando si vuole matchare un punto letterale. 3.14 come regex matcha "3X14", "3 14", "3.14" — qualsiasi carattere al posto del punto. Usa 3\.14 per il punto letterale.

Catastrophic backtracking

Pattern come (a+)+ o (a|aa)+ su input che non matchano possono impiegare secondi, minuti o bloccare il motore regex. Il motore esplora esponenzialmente tutte le combinazioni possibili prima di arrendersi. Evita: quantificatori annidati sugli stessi caratteri, alternazione di pattern che si sovrappongono.

ReDoS (Regex Denial of Service): i web server che accettano regex da utenti non fidati sono vulnerabili a attacchi ReDoS — input appositamente costruiti che fanno impazzire il motore regex. Valida sempre le regex degli utenti con un timeout o usa un motore regex lineare.

Ancora dimenticata

/\d+/ matcha qualsiasi stringa che contiene almeno una cifra — incluse "abc123" e "x1y". Per validare che l'intera stringa sia composta solo da cifre, usa /^\d+$/ con le ancore ^ e $.

Charset e Unicode

\w in JavaScript senza il flag u copre solo ASCII ([a-zA-Z0-9_]) — non matcha lettere accentate come è, à, ü. Per testo internazionale usa /[\p{L}\p{N}_]+/u con le Unicode property escapes.

Regex in JavaScript: i metodi essenziali

// Test: restituisce true/false /^\d+$/.test("123") // true /^\d+$/.test("abc") // false // Match: restituisce array con il primo match (o null) "hello world".match(/\w+/) // ["hello"] // Match global: tutti i match "a1 b2 c3".match(/\w+/g) // ["a1", "b2", "c3"] // MatchAll: tutti i match con gruppi (ES2020+) for (const m of "2026-01-15".matchAll(/(\d+)/g)) { console.log(m[0], m[1]) // "2026" "2026", "01" "01", "15" "15" } // Replace: sostituisci match "2026-04-25".replace(/(\d{4})-(\d{2})-(\d{2})/, "$3/$2/$1") // → "25/04/2026" // Replace con funzione "hello world".replace(/\b\w/g, c => c.toUpperCase()) // → "Hello World" // Split con regex "uno due tre".split(/\s+/) // ["uno", "due", "tre"]

FAQ

Cosa significa il punto in una regex?

Il punto è un metacarattere che matcha qualsiasi carattere tranne il newline. Per matchare un punto letterale, escapalo con backslash: \.. Con il flag s (dotAll), il punto matcha anche il newline.

Differenza tra greedy e lazy?

Greedy (+, *) cattura il massimo possibile. Lazy (+?, *?) cattura il minimo. Su <b>testo</b>, <.+> cattura tutto, <.+?> cattura ogni tag separatamente.

Come matchare lettere accentate italiane?

Aggiungi le lettere esplicitamente alla classe: [a-zàèéìíîòóùú]. Oppure usa Unicode property escapes con il flag u: /[\p{L}]+/u matcha qualsiasi lettera Unicode incluse le accentate.

Le regex JavaScript sono diverse da Python?

La sintassi di base è quasi identica. Le differenze principali: Python usa re.compile() e re.match()/re.search() invece dei metodi su stringa; i flag hanno nomi diversi (re.IGNORECASE invece di /i); Python supporta i lookbehind di lunghezza variabile con il modulo regex (non il built-in re).

Cos'è il catastrophic backtracking?

Pattern con quantificatori annidati sugli stessi caratteri (es. (a+)+) possono impiegare tempo esponenziale su input che non matchano — bloccando il browser o il server. Evita pattern ambigui e testa sempre le regex con input che NON devono matchare.