Skip to content

Guide

Cheat sheet regex: i pattern comuni che ogni sviluppatore conosce

Venticinque pattern che userete davvero, la distinzione greedy/lazy che causa la metà dei bug regex, e dove JavaScript regex differisce da PCRE.

By Published

Una regex funzionante non è un one-liner da memorizzare; è un one-liner più le ipotesi sull’input e sulla variante. Questo cheat sheet abbina ogni pattern a ciò che effettivamente corrisponde, i casi limite che manca, e in quali motori regex funziona. Incollare qualsiasi di essi nel nostro tester regex live per vedere le corrispondenze e le catture in modo interattivo.

Notazione usata di seguito

I pattern sono mostrati senza i delimitatori /.../ circostanti tranne dove le flag contano. Assumere che ^ e $siano ancorati a un singolo valore (l’intero campo), non multi-riga. Quando un pattern usa funzionalità non universali, la nota sulla variante specifica in quali motori funziona. Dove ci sono sia una forma permissiva che una rigorosa, vengono fornite entrambe.

Identificatori e nomi

Email — permissivo

^[^\s@]+@[^\s@]+\.[^\s@]+$

Tre classi di caratteri separate da @ e ., nessuna delle quali contiene spazi bianchi o un altro @. Accetta quasi tutte le email del mondo reale e rifiuta gli errori di battitura più evidenti. Non valida secondo RFC 5322 — le parti locali tra virgolette e i domini IP-literal passano o vengono rifiutati a seconda dell’angolo.

Email — specifica form HTML5

^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$

Il pattern che WHATWG specifica per input type=“email“in HTML. Più rigoroso della forma permissiva ma non dichiara la copertura completa RFC 5322 — la specifica dice esplicitamente “deliberatamente non conforme.” Usarlo quando si vuole abbinare il comportamento del browser.

URL — solo HTTPS

^https://[^\s/$.?#].[^\s]*$

URL HTTPS permissivo. Rifiuta ovvie spazzature ma accetta qualsiasi cosa dopo l’host che non sia spazio bianco. Per la validazione reale, delegare a new URL() nel linguaggio host; regex è per filtrare gli input, non per analizzarli.

Slug (identificatore sicuro per URL)

^[a-z0-9]+(?:-[a-z0-9]+)*$

Lettere minuscole e cifre con trattini singoli tra i gruppi. Nessun trattino iniziale o finale, nessun doppio trattino. Questa è la forma dello slug che ogni CMS usa.

Nome utente — alfanumerico e underscore, 3-20 caratteri

^[A-Za-z0-9_]{3,20}$

UUID (qualsiasi versione)

^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$

UUID v4 (rigoroso)

^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$

Impone il 4 in posizione 13 e i bit variante in posizione 17 (uno di 8, 9, a, b). Usare quando si tiene alla versione, non solo alla forma.

Numeri, valute, codici

Numero intero (con segno)

^-?\d+$

Numero decimale (con segno, parte frazionaria opzionale)

^-?\d+(?:\.\d+)?$

Importo valuta (stile USA)

^\$?\d{1,3}(?:,\d{3})*(?:\.\d{2})?$

Segno del dollaro opzionale, separatori delle migliaia ogni tre cifre, centesimi a due decimali opzionali. Non gestisce i negativi; per la contabilità, anteporre ^-? o racchiudere tra parentesi.

Colore hex (3, 4, 6 o 8 cifre)

^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$

Le forme a 4 e 8 cifre includono un canale alpha (#RRGGBBAA) supportato da CSS Color Level 4 e ogni browser moderno.

Versione semantica (semver 2.0.0)

^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$

Questa è la regex canonica pubblicata su semver.org. Cattura major, minor, patch, pre-release opzionale e metadati di build opzionali. Rifiuta correttamente gli zeri iniziali nelle componenti numeriche.

Date e orari

Data ISO 8601 (YYYY-MM-DD)

^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$

Limita il mese a 01-12 e il giorno a 01-31. Non valida che il giorno esista nel mese dato (il 30 febbraio passa). Per la validazione reale delle date, analizzare con il linguaggio host e verificare la presenza di errori.

Timestamp ISO 8601 con fuso orario

^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$

Accetta Z per UTC o un offset numerico come +02:00. Consente secondi frazionari opzionali.

Ora HH:MM a 24 ore

^(?:[01]\d|2[0-3]):[0-5]\d$

Indirizzi di rete

IPv4

^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$

Intervallo degli ottetti strettamente 0-255. Rifiuta gli zeri iniziali come 192.168.001.001 (che è inequivocabile per gli esseri umani ma alcuni sistemi interpretano come ottale, quindi il rifiuto è difendibile).

IPv6 — pratico

^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$

Corrisponde alla forma canonica a otto gruppi. Non corrisponderà a IPv6 con compressione :: o con IPv4 incorporato come ::ffff:192.0.2.1. La regex completa RFC 4291 supera il centinaio di caratteri; per uso in produzione, delegare all’equivalente inet-pton del proprio linguaggio.

Indirizzo MAC

^(?:[0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}$

Numero di porta

^(?:6553[0-5]|655[0-2]\d|65[0-4]\d{2}|6[0-4]\d{3}|[1-5]\d{4}|[1-9]\d{0,3}|0)$

0-65535, rigorosamente delimitato.

Numeri di telefono

Telefono USA — permissivo

^(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$

+1 opzionale, parentesi opzionali attorno al prefisso, separatori opzionali di trattino, punto o spazio. Accetta i formati USA comuni; rifiuta i numeri non USA.

Telefono internazionale (E.164)

^\+[1-9]\d{1,14}$

E.164 è la specifica ITU: + iniziale, prefisso paese che inizia con un non-zero, lunghezza totale da 2 a 15 cifre incluso il prefisso. Nessuno spazio, nessuna parentesi. Questo è il formato che ogni gateway SMS e la maggior parte dei CRM si aspettano.

Stringhe e struttura

Stringa solo con spazio bianco

^\s*$

Rimuovere spazi iniziali/finali (sostituire con vuoto)

^\s+|\s+$

Collassare spazi multipli in uno (sostituire con spazio singolo)

\s{2,}

Corrispondere contenuto tra parentesi (lazy)

\[([^\]]*)\]

Cattura i caratteri che non sono una parentesi chiusa — la classe di caratteri negata è il modo più pulito per fare un “tutto fino al prossimo delimitatore” non greedy.

Comportamento dei quantificatori

Greedy (il default)

*, +, ? e {n,m} corrispondono il più possibile per default, poi si ritirano per trovare una corrispondenza per il resto del pattern. Su <b>ciao</b><b>arrivederci</b>, il pattern <b>.*</b>corrisponde all’intera stringa, non alla prima coppia di tag.

Lazy (suffisso ?)

Aggiungere un ? per fare in modo che un quantificatore corrisponda il meno possibile. <b>.*?</b> corrisponde solo a <b>ciao</b>, che è quasi sempre quello che si voleva.

Quantificatori possessivi e gruppi atomici

I quantificatori possessivi (*+, ++) e i gruppi atomici ((?>...)) si rifiutano di fare backtracking una volta abbinati. Eliminano il backtracking catastrofico su input patologici. PCRE, Java e Ruby li supportano; JavaScript no (usare un workaround come un lookahead con un back-reference).

Lookahead e lookbehind

I lookaround affermano una condizione senza consumare caratteri. Sono a larghezza zero.

  • Lookahead positivo (?=...) — “seguito da.” \d+(?=px) corrisponde alle cifre seguite da px senza includere pxnella corrispondenza.
  • Lookahead negativo (?!...) — “non seguito da.” foo(?!bar) corrisponde a foo non seguito da bar.
  • Lookbehind positivo (?<=...)— “preceduto da.”
  • Lookbehind negativo (?<!...)— “non preceduto da.”

JavaScript supporta il lookahead in tutte le versioni, il lookbehind solo da ES2018 in poi. Molti motori più vecchi (e la versione V8 in alcune build Node in bundle) limitano i lookbehind a pattern a larghezza fissa; PCRE e il modulo regex di Python consentono larghezza variabile.

Differenze tra varianti da ricordare

  • JavaScript: nessun quantificatore possessivo, nessun gruppo atomico, lookbehind da ES2018. Il flag g (globale) fa sì che String.match restituisca tutte le corrispondenze ma String.replacesi comporti diversamente — l’angolo più pieno di bug di JS regex.
  • PCRE (Perl Compatible): il superset di funzionalità. Usato da PHP, nginx, molti strumenti da riga di comando. Pattern ricorsivi, condizionali, quantificatori possessivi, gruppi atomici, catture nominate — tutti supportati.
  • Python: il modulo standard re è vicino a PCRE meno alcune funzionalità. Il modulo di terze parti regex aggiunge il resto più i lookbehind a larghezza variabile e i gruppi atomici.
  • Go (RE2): deliberatamente a tempo lineare. Nessun backreference, nessun lookaround. Più lento su pattern semplici, immune al backtracking catastrofico. Il crateregex di Rust appartiene alla stessa famiglia.
  • .NET: simile a PCRE, più alcune funzionalità uniche come i gruppi di bilanciamento (che permettono effettivamente di abbinare le parentesi nidificate — in un modo che nessun’altra variante può).

Un flag da evidenziare tra le varianti: Unicode property escapes (\p{Letter}, \p{Number}, \p{Script=Greek}) corrispondono per categoria di codepoint invece che per byte grezzo. JavaScript richiede il flag u, PCRE richiede (*UCP) o il modificatore /u, Python li supporta nel modulo di terze parti regex. Senza di essi, \w significa solo ASCII [A-Za-z0-9_]e il pattern “corrisponde a qualsiasi nome” rifiuta silenziosamente metà del mondo.

I pattern da non scrivere mai

  • Parsing HTML. Usare un vero parser (DOMParser nel browser, BeautifulSoup in Python, go-html in Go). Regex può estrarre un singolo attributo da una forma ben conosciuta, niente di più.
  • Parsing JSON. Ogni linguaggio ha JSON.parse. Usarlo.
  • Parsing di linguaggi di programmazione. Usare un combinatore di parser o una vera grammatica.
  • Qualsiasi cosa che abbia bisogno di abbinare delimitatori nidificati.I linguaggi regolari classici non sanno contare. Usare un parser.

La conclusione onesta

Regex è uno strumento affilato con un dominio piccolo e ben compreso: stringhe a forma fissa, filtraggio semplice degli input, ricerca e sostituzione negli editor di testo. I pattern in questo cheat sheet coprono l’80% dei casi che emergono nel codice quotidiano. Per il 20% che sembra regex-shaped ma non lo è — strutture nidificate, corrispondenza in linguaggio naturale, validazione semantica — ricorrere a un parser.

E quando si scrive una regex, incollarla nel nostro tester con tre input rappresentativi e tre input patologici prima di eseguire il commit. Il pattern che funziona sul proprio unico caso di test è il pattern che fa cadere la produzione su quello di qualcun altro.

Frequently asked questions

Perché la mia regex email rifiuta indirizzi validi?
Perché la grammatica RFC 5322 per gli indirizzi email validi occupa più di una pagina e include costrutti come parti locali tra virgolette ("nome utente"@esempio.com) e domini IP-literal (utente@[192.168.0.1]). La maggior parte delle 'regex email' applica un piccolo sottoinsieme comune. Per la validazione reale, inviare un'email di conferma — la regex può solo filtrare gli errori di battitura evidenti.
La variante regex è davvero così diversa tra i linguaggi?
Sì. JavaScript supporta il lookahead ma ha ottenuto il lookbehind solo nel 2018 (ES2018) e i gruppi nominati nella stessa versione. Python usa re per la regex di base e regex per le funzionalità avanzate come i pattern ricorsivi. PCRE ha le funzionalità più ricche ed è la più vicina a un 'superset regex'. .NET ha le sue peculiarità. Testare sempre nel runtime effettivo, non su regex101 con la variante sbagliata selezionata.
Quantificatori greedy vs lazy — quale voglio?
Greedy (il default) corrisponde il più possibile; lazy (suffisso ?) corrisponde il meno possibile. Per .* all'interno di tag HTML, quasi sempre si vuole lazy: .*? — altrimenti <b>ciao</b><b>arrivederci</b> corrisponde tutto dalla prima <b> all'ultima </b>. Per il parsing numerico dove la lunghezza del campo è nota, greedy è di solito corretto.
Quando non dovrei usare regex?
Parsing di HTML, JSON, YAML, linguaggi di programmazione, o qualsiasi cosa con struttura nidificata. Regex è uno strumento per linguaggi regolari; nel momento in cui si ha bisogno di contare o ricorrere (corrispondenza di parentesi nidificate, corrispondenza di tag aperti/chiusi), usare un vero parser. La risposta di Stack Overflow su 'analizzare HTML con regex' è diventata un classico del culto perché il consiglio è corretto.
Qual è il modo più sicuro per validare un URL?
Passarlo al costruttore URL nel linguaggio effettivo — new URL(input) di JavaScript, urllib.parse.urlparse di Python, java.net.URI di Java. Questi implementano le RFC pertinenti e gestiscono i casi limite (domini internazionali, intervalli di porta, validazione dello schema) che una regex non gestirà. Usare regex solo per filtrare la plausibilità sintattica prima di quella chiamata.
Perché la mia regex è così lenta su certi input?
Backtracking catastrofico. I pattern con quantificatori nidificati o sovrapposti — come (a+)+ o (.*).* — possono richiedere tempo esponenziale su certi input. Il global outage di Cloudflare nel luglio 2019 è stato causato esattamente da una regex del genere. Mitigazioni: evitare quantificatori nidificati, usare gruppi atomici (?>...) o quantificatori possessivi nelle varianti che li supportano, o usare un motore a tempo lineare come regex di Rust o RE2 di Google.

Related

Published May 31, 2026