Regular Expressions
Référence arrière
Recherche…
Les bases
Les références arrière sont utilisées pour correspondre au même texte précédemment associé à un groupe de capture. Cela permet à la fois de réutiliser les parties précédentes de votre modèle et d'assurer deux parties d'une chaîne.
Par exemple, si vous essayez de vérifier qu'une chaîne a un chiffre compris entre zéro et neuf, un séparateur, tel que des traits d'union, des barres obliques ou même des espaces, une lettre minuscule, un autre séparateur, utilisez une regex comme ceci:
[0-9][-/ ][a-z][-/ ][0-9]
Cela correspondrait à 1-a-4
, mais cela correspondrait aussi à 1-a/4
ou 1 a-4
. Si nous voulons que les séparateurs correspondent, nous pouvons utiliser un groupe de capture et une référence arrière. La référence arrière examine la correspondance trouvée dans le groupe de capture indiqué et vérifie que l'emplacement de la référence arrière correspond exactement.
En utilisant notre même exemple, le regex deviendrait:
[0-9]([-/ ])[a-z]\1[0-9]
Le \1
indique le premier groupe de capture du motif. Avec ce petit changement, le regex correspond maintenant à 1-a-4
ou 1 a 4
mais pas 1 a-4
ou 1-a/4
.
Le nombre à utiliser pour votre référence arrière dépend de l'emplacement de votre groupe de capture. Le nombre peut être compris entre un et neuf et peut être trouvé en comptant vos groupes de capture.
([0-9])([-/ ])[a-z][-/ ]([0-9])
|--1--||--2--| |--3--|
Les groupes de capture imbriqués modifient légèrement ce nombre. Vous comptez d'abord le groupe de capture extérieur, puis le niveau suivant, et continuez jusqu'à ce que vous quittiez le nid:
(([0-9])([-/ ]))([a-z])
|--2--||--3--|
|-------1------||--4--|
Références ambiguës
Problème: Vous devez faire correspondre le texte d'un certain format, par exemple:
1-a-0
6/p/0
4 g 0
C'est un chiffre, un séparateur (un des -
, /
ou un espace), une lettre, le même séparateur et un zéro.
Solution naïve: en adaptant la regex à l' exemple de base , vous obtenez cette regex:
[0-9]([-/ ])[a-z]\10
Mais cela ne fonctionnera probablement pas. La plupart des versions de regex prennent en charge plus de neuf groupes de capture, et très peu d'entre elles sont suffisamment intelligentes pour comprendre que, puisqu'il n'y a qu'un groupe de capture, \10
doit être une référence au groupe 1 suivi d'un littéral 0
. La plupart des saveurs le traiteront comme une référence rétroactive au groupe 10. Quelques-unes d’entre elles lanceront une exception car il n’ya pas de groupe 10; le reste échouera tout simplement.
Il y a plusieurs façons d'éviter ce problème. L'une consiste à utiliser des groupes nommés (et des références nommées):
[0-9](?<sep>[-/ ])[a-z]\k<sep>0
Si votre langage regex le prend en charge, le format \g{n}
(où n
est un nombre) peut contenir le numéro de référence arrière entre accolades pour le séparer des chiffres suivants:
[0-9]([-/ ])[a-z]\g{1}0
Une autre méthode consiste à utiliser un format regex étendu, en séparant les éléments avec des espaces non significatifs (en Java, vous devrez échapper de l'espace entre crochets):
(?x) [0-9] ([-/ ]) [a-z] \1 0
Si votre version regex ne prend pas en charge ces fonctionnalités, vous pouvez ajouter une syntaxe inutile mais inoffensive, comme un groupe non capturant:
[0-9]([-/ ])[a-z](?:\1)0
... ou un quantificateur factice (c'est peut-être la seule circonstance où {1}
est utile):
[0-9]([-/ ])[a-z]\1{1}0