La regex è pronta: metà dei casi di test corrisponde, gli altri no. La parte costosa non è mai scriverla, ma capire perché. Le tre trappole qui sotto coprono la maggior parte dei casi e ognuna ha un ordine di verifica preciso.
Distinguere i due tipi di fallimento
Nessuna corrispondenza e corrispondenza con contenuto sbagliato sono problemi diversi. Il primo di solito indica una classe di caratteri o un flag errato; il secondo quasi sempre dipende da quantificatori golosi e dalla posizione delle parentesi. Capire quale dei due hai davanti fa risparmiare metà del tempo: prima verifica se c'è corrispondenza, poi cosa ha catturato il gruppo 1.
Trappola 1: il quantificatore goloso si mangia il resto
.* è goloso per impostazione predefinita: arriva a fine riga e poi torna indietro. Perciò title="(.*)" su title="a" id="b" cattura a" id="b, non a.
Due rimedi: rendere il quantificatore pigro (.*?) oppure usare una classe di caratteri precisa ([^"]*). La seconda è di solito più veloce e prevedibile — i quantificatori pigri tornano comunque indietro, le classi no.
Trappola 2: un livello di escaping di troppo (o mancante)
Se la regex sta in un literal stringa, i backslash passano per due parser. In JavaScript scrivi \\d per ottenere la regex \d; copiando \\\\d da altrove il pattern cerca un backslash letterale seguito da d. Lo stesso vale per \s, \. e \/.
Verifica rapida: stampa la stringa finale del pattern nel debugger e confrontala con quella che pensavi di aver scritto. Questo risolve gran parte dei casi «l'ho scritto, ma non corrisponde».
Trappola 3: i flag m e g
Senza m, ^ e $ corrispondono solo all'inizio e alla fine dell'intera stringa, quindi il confronto riga per riga su testi multiriga fallisce. Con m rispettano i confini di ogni riga.
Con g, l'oggetto regex ricorda dove è finita l'ultima corrispondenza (lastIndex). Riusando la stessa regex globale in un ciclo, la seconda chiamata riparte da lì e sembra saltare delle corrispondenze. Crea una nuova istanza per iterazione oppure azzera lastIndex.
Metodo in quattro passi
- Riduci l'input: taglia la stringa alla versione più corta che riproduce l'errore
- Dividi il pattern: separa su
|o elimina le parti opzionali finché non trovi il punto che fallisce - Guarda i gruppi: controlla cosa contiene davvero ogni gruppo
- Prova altri input: aggiungi una stringa che deve corrispondere e una che non deve
Il quarto passo è quello che si salta più spesso. Una corrispondenza non dimostra che il pattern rifiuti il resto — le corrispondenze di troppo fanno danni maggiori, per esempio sostituendo un intero frammento HTML al posto del solo testo.
Una nota sulle prestazioni
Quantificatori annidati come (a+)+$ su input lunghi e non corrispondenti causano backtracking catastrofico e possono bloccare il browser per secondi. Il test è semplice: raddoppia la lunghezza dell'input e guarda se il tempo cresce più di quattro volte. Se succede, non usare quel pattern direttamente sull'input dell'utente.
In una frase
Prima stabilisci se manca la corrispondenza o se il contenuto è sbagliato, poi controlla golosità, escaping e flag in quest'ordine.
I tre numeri da leggere per primi
Quando aprite un tester di espressioni regolari, ignorate per un momento l'evidenziazione colorata e guardate prima queste tre cose:
- Il numero totale di corrispondenze. Zero significa «non ha corrisposto nulla» — un problema di classe di caratteri o di flag. Più di zero ma meno del previsto di solito indica il flag
gmancante, oppure una parte del pattern che inghiotte tutto ciò che segue. - La posizione iniziale e finale di ogni corrispondenza. Le posizioni spiegano più del contenuto: se la prima corrispondenza arriva fino a fine testo, c'è un quantificatore greedy al lavoro.
- Cosa ha davvero catturato il gruppo 1. Guardare il gruppo isolato separa subito «non ha corrisposto» da «ha corrisposto ma ha preso la cosa sbagliata».
L'ordine conta: prima il conteggio, poi le posizioni, infine i gruppi. Al contrario, l'evidenziazione colorata trascinerà lo sguardo finché tutto sembrerà sbagliato.
Tre punti ciechi con CJK e Unicode
w è la scorciatoia per [A-Za-z0-9_] e non contiene alcun carattere CJK: w+ su «张三» non restituisce nulla. Per il testo cinese usate [一-龥] o l'intervallo più ampio [一-鿿].
. non corrisponde a un a capo senza il flag s. Su testo multiriga, .* si ferma a fine prima riga. O usate [sS]* o attivate s.
I confini di parola sono quasi inutili per il cinese: le parole non sono separate da spazi e non esiste un confine da trovare. La segmentazione richiede una libreria dedicata, non una regex.
Un'altra cosa: la punteggiatura cinese è a larghezza piena. , e , sono punti di codice diversi, quindi un modulo che valida sulla virgola a mezza larghezza rifiuterà chi ne digita una a larghezza piena.
Fissate il pattern con una tabella di casi
«Passava durante il test» non significa che la regex sia corretta. L'approccio duraturo è da tre a cinque casi per pattern, scritti in una piccola tabella:
- Deve corrispondere: un input normale più i casi limite — il più corto, il più lungo, esattamente sul bordo.
- Non deve corrispondere: stringa vuota, solo spazi, dati sporchi con prefissi o suffissi in più.
- Facile da far corrispondere per errore: input simili ma di classe diversa — per un numero di telefono, uno con prefisso o un fisso che inizia per 1.
La tabella ripaga più avanti: quando qualcuno modificherà il pattern sei mesi dopo, eseguire i casi mostrerà subito se il comportamento precedente si è rotto. Senza tabella, ogni modifica è alla cieca.
Dove non usare una regex
Le regex non sono uno strumento universale, e in certi punti falliscono per costruzione:
- Analizzare HTML o XML annidati. I tag si annidano arbitrariamente e le regex non hanno ricorsione.
<div>.*?</div>si fermerà sempre al primo tag di chiusura sbagliando la struttura esterna. Serve un parser DOM. - Analizzare JSON. Le stringhe possono contenere escape e parentesi graffe arbitrarie, che una regex fraintende. Serve
JSON.parse. - Validare completamente un indirizzo email. La RFC 5322 ammette una varietà enorme di forme, e inseguire la precisione al 100% è difficile da scrivere e da mantenere. In pratica: limitate la lunghezza, richiedete una
@e almeno un punto, poi inviate una mail di conferma. - Input molto lunghi. Un pattern con quantificatori annidati fa backtracking esponenziale su decine di migliaia di caratteri non corrispondenti e blocca il browser. Limitate prima la lunghezza.
Il criterio è semplice: la struttura di destinazione ammette annidamento arbitrario o ricorsione? Se sì, non usate una regex.