13 maggio 2021

Riferimenti all'indietro (backreference) nei pattern: \N e \k<name>

Possiamo usare il contenuto dei gruppi di acquisizione (...) non soltanto nel risultato o nella stringa di sostituzione, ma anche all’interno del pattern stesso.

Riferimento all’indietro per numero: \N

Ci si può riferire ad un gruppo nel pattern usando \N, in cui N indica il numero del gruppo.

Per comprendere chiaramente perché sia utile, consideriamo l’esercitazione seguente.

Dobbiamo trovare le stringhe tra apici: sia quelli singoli '...' sia quelli doppi "...", entrambi devono dare luogo a riscontro.

Come trovarli?

Potremmo mettere i due tipi di apici all’interno di parentesi quadre: ['"](.*?)['"], ma in questo modo troveremmo anche le stringhe con apici misti come "...' e '...". Questo porterebbe a risultati inesatti quando un tipo di apice compare tra due dell’altro tipo, come nella stringa "She's the one!":

let str = `He said: "She's the one!".`;

let regexp = /['"](.*?)['"]/g;

// Il risultato non è quello che vorremmo
alert( str.match(regexp) ); // "She'

Come possiamo osservare, il pattern ha trovato un apice di apertura ", quindi il testo fino al successivo apice ' che chiude la corrispondenza.

Per accertarci che il pattern trovi l’apice di chiusura uguale a quello di apertura, possiamo racchiuderlo in un gruppo di acquisizione e fare riferimento ad esso: (['"])(.*?)\1.

Ecco il codice corretto:

let str = `He said: "She's the one!".`;

let regexp = /(['"])(.*?)\1/g;

alert( str.match(regexp) ); // "She's the one!"

Ora funziona! L’interprete dell’espressione regolare trova il primo apice (['"]) e lo memorizza. Questo è il primo gruppo di acquisizione.

Più avanti nel pattern \1 significa “trova lo stesso testo del primo gruppo”, nel nostro caso esattamente lo stesso apice.

Similmente \2 indicherebbe il contenuto del secondo gruppo, \3 quello del terzo gruppo, e così via.

Da notare:

Se nel gruppo usiamo ?: non sarà possibile riferirsi ad esso. I gruppi esclusi dall’acquisizione (?:...) non sono memorizzati dall’interprete.

Non fare confusione: nel pattern \1, nelle sostituzioni $1

Nelle sostituzioni di stringa si adopera il segno di dollaro: $1, mentre nel contesto di un pattern il backslash \1.

Riferimento all’indietro per nome: \k<name>

Se un’espressione regolare ha tante parentesi, è opportuno dare loro dei nomi.

Per riferirsi ad un gruppo nominato si usa \k<name>.

Nell’esempio sotto il gruppo con gli apici è nominato ?<quote>, pertanto il riferimento è \k<quote>:

let str = `He said: "She's the one!".`;

let regexp = /(?<quote>['"])(.*?)\k<quote>/g;

alert( str.match(regexp) ); // "She's the one!"
Mappa del tutorial

Commenti

leggi questo prima di lasciare un commento…
  • Per qualsiasi suggerimento - per favore, apri una issue su GitHub o una pull request, piuttosto di lasciare un commento.
  • Se non riesci a comprendere quanto scitto nell'articolo – ti preghiamo di fornire una spiegazione chiara.
  • Per inserire delle righe di codice utilizza il tag <code>, per molte righe – includile nel tag <pre>, per più di 10 righe – utilizza una sandbox (plnkr, jsbin, codepen…)