Groupes et références arrière

Les groupes permettent de regrouper différents motifs ensemble et les groupes de capture permettent d'extraire des informations supplémentaires quant aux correspondances entre une expression rationnelle et une chaîne de caractères. Les références arrière correspondent au groupe précédemment capturé dans la même expression rationnelle.

Exemple interactif

Types

Caractères Signification
(x)

Groupe de capture : correspond à x et mémorise la correspondance. Ainsi, /(toto)/ correspond à "toto" dans la chaîne de caractères `"toto truc"` et mémorise cette correspondance.

Une expression rationnelle peut avoir plusieurs groupes de capture. Dans les résultats, les correspondances des groupes de capture sont dans un tableau dont les éléments sont généralement dans le même ordre que les parenthèses gauches des groupes de capture. Il s'agit la plupart du temps de l'ordre des groupes de capture, mais peut aider lorsqu'il y a une imbrication de ces groupes. On accède aux correspondances en utilisant les indices du résultat ([1], …, [n]) ou avec les propriétés objets prédéfinies de RegExp ($1, …, $9).

Les groupes de capture ont un impact sur les performances. Si vous n'avez pas besoin de mémoriser les correspondances, préférez l'utilisation des parenthèses non-capturantes (voir ci-après).

String.match() ne retournera pas de groupes si le marqueur /.../g est actif. Toutefois, il reste possible d'utiliser String.matchAll() pour obtenir toutes les correspondances.

(?<Nom>x)

Groupe de capture nommé : correspond à x et enregistre cette correspondance dans la propriété groups des correspondances renvoyées aevc le nom fourni <Nom>. Les chevrons (< and >) sont nécessaire pour indiquer le nom du groupe.

Ainsi, pour extraire le code de zone d'un numéro de téléphone américain, on pourra utiliser /\((?<area>\d\d\d)\)/. Le numéro correspondant serait alors accessible via matches.groups.area.

(?:x) Groupe non-capturant : correspond à x mais ne mémorise pas cette correspondance. La sous-chaîne de caractères correspondante ne peut pas être récupérée depuis les éléments du tableau résultant ([1], …, [n]) ou depuis les propriétés prédéfinies de l'objet RegExp ($1, …, $9).
\n n est un entier positif. Une référence arrière à la dernière sous-chaîne correspondant au n-ième groupe (selon l'ordre des parenthèses gauches). Ainsi, /pomme(,)\sorange\1/ correspond à "pomme, orange," dans la chaîne de caractères "pomme, orange, cerise, pêche".
\k<Nom>

Une référence arrière à la dernière correspondance du groupe de capture nommé désigné par <Nom>.

Ainsi, /(?<titre>\w+), oui \k<titre>/ correspondra à "Chef, oui Chef" dans "Bien reçu ? Chef, oui Chef !".

Note : \k est utilisé ici de façon littérale pour indiquer le début d'une référence arrière vers un groupe de capture nommé.

Exemples

Utiliser les groupes

const listePersonnes = `Prénom : Jean, Nom_famille : Biche
Prénom : Jeanne, Nom_famille : Ferrant`;

const regexpNames =  /Prénom : (\w+), Nom_famille : (\w+)/mg;
for (const correspondance of listePersonnes.matchAll(regexpNames)) {
  console.log(`Bonjour ${correspondance[1]} ${correspondance[2]}`);
}

Utiliser les groupes nommés

const listePersonnes = `Prénom : Jean, Nom_famille : Biche
Prénom : Jeanne, Nom_famille : Ferrant`;

const regexpNames =  /Prénom : (?<prenom>\w+), Nom_famille : (?<nom>\w+)/mg;
for (const correspondance of listePersonnes.matchAll(regexpNames)) {
  console.log(`Bonjour ${correspondance.groups.prenom} ${correspondance.groups.nom}`);
}

Utiliser les groupes et les références arrière

const citation = `Simple quote "'" et double quote '"'`;
const regexpQuotes = /(['"]).*?\1/g;
for (const correspondance of citation.matchAll(regexpQuotes)) {
  console.log(correspondance[0]);
}

Utiliser les groupes et les indices de correspondance

En utilisant le marqueur d, les indices de chaque groupe capturant sont renvoyés. Cela s'avère notamment utile si on veut établir des liens entre chaque groupe et le texte d'origine, par exemple pour fournir des diagnostics avec un compilateur.

const code = `function add(x, y) {
  return x + y;
}`;
const functionRegexp =
  /(function\s+)(?<name>[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*)/du;
const match = functionRegexp.exec(code);
const lines = code.split("\n");
lines.splice(
  1,
  0,
  " ".repeat(match.indices[1][1] - match.indices[1][0]) +
    "^".repeat(match.indices.groups.name[1] - match.indices.groups.name[0])
);
console.log(lines.join("\n"));
// function add(x, y) {
//          ^^^
//   return x + y;
// }

Voir aussi