La mia regex funziona nel tester ma non nel codice — ecco perché
Il pattern non è quasi mai il problema. Sono l'escaping, i flag o un motore di regex diverso — e ognuno ha un sintomo caratteristico che ti dice con quale dei tre hai a che fare.
Costruisci un pattern in un tester online, corrisponde perfettamente, lo incolli nel codice e non corrisponde a nulla. La regex non è cambiata, quindi è cambiato qualcosa attorno. In pratica è una di tre cose: il pattern è stato rovinato dall'escaping in una stringa, i flag non hanno viaggiato con lui, oppure il tuo linguaggio usa un motore di regex diverso da quello del tester.
Escaping: il pattern nel tuo codice non è quello che hai scritto
Questa è di gran lunga la causa più comune, e accade ogni volta che la regex vive dentro una stringa anziché in un letterale di espressione regolare. In una stringa la barra rovesciata è essa stessa un carattere di escape, quindi viene consumata prima che il motore di regex la veda. Il tuo \d diventa una semplice d, e \. diventa un punto letterale che ora corrisponde a qualsiasi carattere. Il pattern che riceve il motore è davvero diverso da quello che hai digitato. La soluzione varia per linguaggio: in JavaScript preferisci la forma letterale /\d+/ a new RegExp("\\d+"); in Python usa una stringa raw, r"\d+"; in Java e C# devi raddoppiare ogni barra rovesciata, oppure usare le stringhe verbatim @"..." di C#.
I flag si configurano a parte e non vengono copiati
I tester online mettono i flag in una casella separata accanto al pattern, quindi quando selezioni e copi porti via il pattern e lasci indietro i flag. Tre contano più degli altri. Il flag m cambia il significato di ^ e $ da "inizio e fine dell'intera stringa" a "inizio e fine di ogni riga" — senza di esso, un pattern che funzionava su un blocco di testo di prova su più righe fallirà. Il flag s consente a . di corrispondere anche agli a capo, cosa che di default non fa. E il flag i per l'insensibilità alle maiuscole è quello di cui più spesso ci si dimentica che era attivo.
Il flag g ha la sua trappola
In JavaScript una regex con il flag g ha stato: mantiene una proprietà lastIndex che avanza dopo ogni corrispondenza. Se riutilizzi lo stesso oggetto regex con .test() dentro un ciclo, ottieni risultati alternati true e false per lo stesso input, il che sembra non determinismo ed è logorante da debuggare. O crei la regex ogni volta, o togli il flag g quando ti serve solo un booleano, o azzeri lastIndex tra una chiamata e l'altra.
Non tutti i motori parlano lo stesso dialetto
La maggior parte dei tester online usa PCRE per impostazione predefinita, il dialetto compatibile con Perl. Il tuo codice potrebbe non usarlo. Le asserzioni lookbehind, i gruppi con nome e i quantificatori possessivi variano nel supporto. L'esempio più netto è RE2, usato da Go e da diversi database, che omette deliberatamente retroriferimenti e lookahead per mantenere lineare il tempo di ricerca — un pattern che vi si appoggia non è che fallisce, proprio non compila. Se il tuo tester ha un selettore di motore, impostalo sul tuo linguaggio reale prima di costruire il pattern, non dopo che si rompe.
Corrispondenza parziale contro corrispondenza completa
I tester mostrano quasi sempre ogni corrispondenza parziale evidenziata nel testo, ma molte API dei linguaggi pongono una domanda diversa. Il matches() di Java richiede che il pattern consumi l'intero input, mentre find() cerca una corrispondenza ovunque — così un pattern che si evidenzia allegramente in un tester restituisce false da matches(). Python ha la stessa divisione in tre tra re.match, re.search e re.fullmatch. Se il tuo pattern sembra corretto ma restituisce false, controlla quale di queste hai chiamato prima di toccare la regex.
Il passo di debug che lo trova più in fretta
Stampa il pattern compilato a runtime — non la riga sorgente, ma il valore reale che il motore ha ricevuto. In JavaScript è String(miaRegex), in Python print(pattern.pattern). Se quello che vedi è diverso da quello che hai scritto, è un problema di escaping e l'hai trovato in un passo solo. Se coincide esattamente, il problema sono i flag o il dialetto, e hai eliminato due terzi delle possibilità senza tirare a indovinare.
Il nostro tester di regex mostra pattern, flag e corrispondenze affiancati ed evidenzia i gruppi mentre scrivi, così puoi confermare l'esatta combinazione di pattern e flag prima che finisca nel tuo codice. Funziona nel tuo browser, quindi puoi testare su dati reali senza rischi.