W3docs

Backreferenze regex nel pattern: \n e \k<name>

Prima di entrare nei dettagli delle backreferenze, capiamo le espressioni regolari in JavaScript. Aiutano a trovare pattern nel testo.

La maggior parte di un'espressione regolare corrisponde a testo fisso, ma a volte occorre trovare testo che deve essere identico a qualcosa già trovato in precedenza — senza sapere in anticipo quale sia. Una backreferenza risolve esattamente questo problema: permette a un pattern di dire "trova la stessa cosa catturata dal gruppo poco fa."

Casi d'uso classici delle backreferenze includono il rilevamento di una parola duplicata (the the), la corrispondenza con una stringa racchiusa in virgolette bilanciate ("..." o '...' ma non "...'), o la verifica che un tag simile a HTML sia chiuso con lo stesso nome. Nulla di tutto ciò è possibile con pattern letterali ordinari, perché il testo da trovare non è noto fino a quando la regex non viene eseguita.

Questa guida tratta le backreferenze numerate (\1, \2, …), quelle con nome (\k<name>), come vengono numerati i gruppi, le insidie più comuni e come riutilizzare il testo catturato in String.prototype.replace().

Come usare le backreferenze

All'interno di un pattern, una barra rovesciata seguita da un numero fa riferimento al testo catturato da un gruppo di cattura. \1 corrisponde a ciò che ha catturato il gruppo 1, \2 al gruppo 2, e così via. Il punto chiave: trova il testo catturato, non di nuovo il pattern del gruppo.

javascript— editable

Qui (\w+) cattura una parola nel gruppo 1, \s trova lo spazio e \1 richiede la stessa parola di nuovo. Quindi hello hello corrisponde, ma hello world no — \1 deve essere uguale a ciò che ha catturato il gruppo 1, non semplicemente trovare di nuovo \w+.

Come vengono numerati i gruppi

I numeri dei gruppi sono assegnati in base alla posizione della parentesi aperta di ciascun gruppo, da sinistra a destra. Questo è importante quando si hanno gruppi multipli o annidati:

javascript— editable

L'intera corrispondenza è il gruppo 0 (m[0]), ecco perché il primo gruppo di cattura è \1 e non \0. Per i gruppi annidati, il gruppo esterno ottiene il numero inferiore perché la sua ( compare per prima.

Usare i gruppi con nome

I riferimenti numerici diventano difficili da leggere quando un pattern cresce. In alternativa, puoi dare un nome a un gruppo con (?<name>…) e farvi riferimento con \k<name>. Per ulteriori informazioni sulla dichiarazione di gruppi con nome, consulta Gruppi di cattura.

javascript— editable

Qui (?<word>\w+) è un gruppo con nome e \k<word> vi fa backreferenza. Dopo una corrispondenza riuscita, il testo catturato è disponibile anche sull'object match.groups. I gruppi con nome e \k<name> funzionano in tutti i browser moderni e nelle versioni correnti di Node.js senza alcun flag.

Riutilizzare le catture in replace()

L'uso quotidiano più comune delle backreferenze non si trova all'interno del pattern, bensì nella stringa di sostituzione di String.prototype.replace(). Lì si fa riferimento al testo catturato con $1, $2, … (o $<name> per i gruppi con nome).

Un esempio utile riduce una parola accidentalmente duplicata a una sola:

javascript— editable

Nota la distinzione: \1 (barra rovesciata) si usa all'interno del pattern, mentre $1 (segno del dollaro) si usa nella stringa di sostituzione. Confonderli è una fonte frequente di bug.

Attenzione: gruppi non partecipanti

Una backreferenza a un gruppo che non ha partecipato alla corrispondenza si comporta in modo speciale. Se il gruppo non ha mai trovato una corrispondenza (ad esempio, era all'interno di un'alternativa non utilizzata), il valore catturato è undefined, e in JavaScript la backreferenza corrisponde allora alla stringa vuota — riesce senza consumare nulla.

javascript— editable

È facile non notarlo: ci si potrebbe aspettare che \1 fallisca quando il gruppo non ha trovato corrispondenza, ma invece corrisponde silenziosamente a nulla. Struttura con cura le alternanze se ti aspetti che un gruppo abbia sempre catturato qualcosa.

Una backreferenza pratica: virgolette bilanciate

Un pattern pratico che richiede una backreferenza è la ricerca di una stringa tra virgolette in cui la virgoletta di chiusura deve essere lo stesso carattere di quella di apertura — "..." e '...' sono valide, ma "...' non lo è.

javascript— editable

Il gruppo (['"]) cattura qualunque carattere di virgoletta abbia aperto la stringa, e \1 obbliga la chiusura a essere esattamente quello stesso carattere. Un semplice ["'].*?["'] non potrebbe imporre questo vincolo — accetterebbe felicemente "...'. Questa è la differenza tra un lookahead/lookbehind (che si limita ad asserire) e una backreferenza (che trova di nuovo il testo catturato).

Conclusione

Usa una backreferenza ogni volta che una parte successiva della corrispondenza deve essere uguale al testo trovato in precedenza — parole doppie, virgolette bilanciate, tag con lo stesso nome, o regole del tipo "i caratteri adiacenti devono differire". Ricorda i tre punti essenziali:

  • I gruppi numerati si contano dalla loro ( di apertura, a partire da \1; l'intera corrispondenza è il gruppo 0.
  • Usa \1 / \k<name> all'interno del pattern, e $1 / $<name> in replace().
  • Un gruppo non partecipante fa sì che la sua backreferenza corrisponda alla stringa vuota, quindi gestisci con attenzione le alternanze.

Per i mattoni di base, consulta Gruppi di cattura, Classi di caratteri e Lookahead e Lookbehind.

Esercitati

Pratica
Quale delle seguenti affermazioni sulle backreferenze nelle espressioni regolari JavaScript è vera?
Quale delle seguenti affermazioni sulle backreferenze nelle espressioni regolari JavaScript è vera?
Was this page helpful?