17 août 2020

Rétro référence dans le pattern : \N et \k<name>

Nous pouvons utiliser le contenu des groupes de capture (...) non seulement dans le résultat ou dans la chaîne de caractères de remplacement, mais également dans le pattern en lui-même.

Rétro référence par un nombre : \N

Un groupe peut être référencé dans le pattern par \N, où N est le numéro du groupe.

Pour rendre son utilité claire, considérons la tâche ci-dessous.

Nous devons trouver des chaînes citées : soit par des apostrophes '...', soit par des guillemets "..." – les deux variantes devraient correspondre.

Comment les trouver ?

Nous pouvons mettre les deux types entre crochets : ['"](.*?)['"], mais ce pattern pourrait correspondre avec des mélanges comme "...' ou '...". Cela mènerait à des correspondances incorrectes lorsqu’une citation apparaît dans une autre, comme dans le texte "She's the one!":

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

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

// Le résultat n'est pas celui que nous aimerions avoir
alert( str.match(regexp) ); // "She'

Comme nous pouvons le voir, le pattern trouve des guillemets ouvrant ", puis le texte est récupéré jusqu’au ', ce qui termine la correspondance.

Pour faire en sorte que le pattern vérifie que le caractère terminant la citation est précisément le même que celui qui l’ouvre, nous pouvons l’envelopper dans un groupe de capture et le rétro référencier : (['"])(.*?)\1.

Voilà le code correct :

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

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

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

Maintenant, ça fonctionne ! Le moteur trouve le premier caractère de citation (['"]) et mémorise son contenu. C’est le premier groupe de capture.

Plus loin dans le pattern, \1 signifie “cherche le même texte que dans le premier groupe de capture”, le même caractère de citation dans notre cas.

Similairement, \2 voudrait référencier le 2nd groupe, \3 – le 3e groupe, et ainsi de suite.

Veuillez noter :

Si nous utilisons ?: dans le groupe, alors nous ne pouvons pas le référencer. Les groupes exclus de la capture (?:...) ne sont pas mémorisés par le moteur.

Ne mélangez pas : dans le pattern, \1, dans le replacement : $1

Dans la chaîne de remplacement, on utilise un signe dollar : $1, alors que dans un pattern – un antislash \1.

Rétro référence par le nom: \k<name>

Si une expression régulière a beaucoup de groupes, il est pratique de leur attribuer un nom.

Pour référencer un groupe nommé, on peut utiliser \k<name>.

Dans l’exemple ci-dessous, le groupe du caractère de citation s’appelle ?<quote>, donc la rétro référence est \k<quote>:

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

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

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

Commentaires

lire ceci avant de commenter…
  • Si vous avez des améliorations à suggérer, merci de soumettre une issue GitHub ou une pull request au lieu de commenter.
  • Si vous ne comprenez pas quelque chose dans l'article, merci de préciser.
  • Pour insérer quelques bouts de code, utilisez la balise <code>, pour plusieurs lignes -- enveloppez-les avec la balise <pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepen…)