Comment les groupes non capturants, c'est-à-dire (?:)
utilisés dans les expressions régulières et à quoi servent-ils?
regex
capturing-group
regex-group
Never_had_a_name
la source
la source
Réponses:
Permettez-moi d'essayer d'expliquer cela avec un exemple.
Considérez le texte suivant:
Maintenant, si j'applique l'expression régulière ci-dessous dessus ...
... j'obtiendrais le résultat suivant:
Mais je ne me soucie pas du protocole - je veux juste l'hôte et le chemin de l'URL. Donc, je modifie l'expression régulière pour inclure le groupe non capturant
(?:)
.Maintenant, mon résultat ressemble à ceci:
Voir? Le premier groupe n'a pas été capturé. L'analyseur l'utilise pour faire correspondre le texte, mais l'ignore plus tard, dans le résultat final.
ÉDITER:
Comme demandé, permettez-moi d'essayer d'expliquer les groupes aussi.
Eh bien, les groupes ont plusieurs objectifs. Ils peuvent vous aider à extraire des informations exactes d'une correspondance plus importante (qui peut également être nommée), ils vous permettent de faire correspondre un groupe correspondant précédent et peuvent être utilisés pour des substitutions. Essayons quelques exemples, d'accord?
Imaginez que vous ayez une sorte de XML ou HTML (sachez que regex n'est peut-être pas le meilleur outil pour le travail , mais c'est bien comme exemple). Vous voulez analyser les balises, vous pouvez donc faire quelque chose comme ça (j'ai ajouté des espaces pour le rendre plus facile à comprendre):
Le premier regex a un groupe nommé (TAG), tandis que le second utilise un groupe commun. Les deux expressions rationnelles font la même chose: elles utilisent la valeur du premier groupe (le nom de la balise) pour correspondre à la balise de fermeture. La différence est que le premier utilise le nom pour correspondre à la valeur et le second utilise l'index de groupe (qui commence à 1).
Essayons maintenant quelques substitutions. Considérez le texte suivant:
Maintenant, utilisons cette expression muette dessus:
Cette expression régulière correspond aux mots d'au moins 3 caractères et utilise des groupes pour séparer les trois premières lettres. Le résultat est le suivant:
Donc, si nous appliquons la chaîne de substitution:
... par-dessus, nous essayons d'utiliser le premier groupe, d'ajouter un trait de soulignement, d'utiliser le troisième groupe, puis le deuxième groupe, d'ajouter un autre trait de soulignement, puis le quatrième groupe. La chaîne résultante serait comme celle ci-dessous.
Vous pouvez également utiliser des groupes nommés pour les substitutions à l'aide de
${name}
.Pour jouer avec les regex, je recommande http://regex101.com/ , qui offre une bonne quantité de détails sur le fonctionnement des regex; il propose également quelques moteurs regex parmi lesquels choisir.
la source
Vous pouvez utiliser des groupes de capture pour organiser et analyser une expression. Un groupe qui ne capture pas a le premier avantage, mais n'a pas les frais généraux du second. Vous pouvez toujours dire qu'un groupe non capturant est facultatif, par exemple.
Supposons que vous vouliez faire correspondre le texte numérique, mais certains nombres pourraient être écrits comme 1er, 2e, 3e, 4e, ... Si vous voulez capturer la partie numérique, mais pas le suffixe (facultatif), vous pouvez utiliser un groupe non capturant .
Cela correspondra aux nombres sous la forme 1, 2, 3 ... ou sous la forme 1er, 2e, 3e, ... mais il ne capturera que la partie numérique.
la source
?:
est utilisé lorsque vous souhaitez regrouper une expression, mais que vous ne souhaitez pas l'enregistrer en tant que partie correspondante / capturée de la chaîne.Un exemple serait quelque chose pour correspondre à une adresse IP:
Notez que je ne me soucie pas de sauvegarder les 3 premiers octets, mais le
(?:...)
regroupement me permet de raccourcir l'expression régulière sans encourir la surcharge de capture et de stockage d'une correspondance.la source
Cela rend le groupe non capturant, ce qui signifie que la sous-chaîne mise en correspondance par ce groupe ne sera pas incluse dans la liste des captures. Un exemple en rubis pour illustrer la différence:
la source
(?:)
cela ne produit pas de capture, pas de démontrer un exemple utile de(?:)
.(?:)
est utile lorsque vous souhaitez regrouper une sous-expression (par exemple lorsque vous souhaitez appliquer des quantificateurs à une sous-expression non atomique ou si vous souhaitez restreindre la portée de a|
), mais que vous ne voulez rien capturer.MOTIVATION HISTORIQUE:
L'existence de groupes non capturants peut s'expliquer par l'utilisation de parenthèses.
Considérez les expressions
(a|b)c
eta|bc
, en raison de la priorité de la concaténation|
, ces expressions représentent deux langues différentes ({ac, bc}
et{a, bc}
respectivement).Cependant, les parenthèses sont également utilisées comme groupe d'appariement (comme expliqué par les autres réponses ...).
Lorsque vous souhaitez avoir des parenthèses mais ne pas capturer la sous-expression, vous utilisez des GROUPES NON CAPTURANTS. Dans l'exemple,
(?:a|b)c
la source
Permettez-moi d'essayer ceci avec un exemple:
Code regex:
(?:animal)(?:=)(\w+)(,)\1\2
Chaîne de recherche:
Ligne 1 -
animal=cat,dog,cat,tiger,dog
Ligne 2 -
animal=cat,cat,dog,dog,tiger
Ligne 3 -
animal=dog,dog,cat,cat,tiger
(?:animal)
-> Groupe 1 non capturé(?:=)
-> Groupe 2 non capturé(\w+)
-> Groupe capturé 1(,)
-> Capturé Groupe 2\1
-> résultat du groupe 1 capturé, c.-à-d. que la ligne 1 est le chat, la ligne 2 le chat, la ligne 3 le chien\2
-> résultat du groupe 2 capturé, c'est-à-dire virgule (,)Donc, dans ce code, en donnant
\1
et\2
nous rappelons ou répétons le résultat des groupes capturés 1 et 2 respectivement plus tard dans le code.Selon l'ordre du code
(?:animal)
doit être le groupe 1 et(?:=)
doit être le groupe 2 et continue ..mais en donnant le
?:
nous faisons le match-group non capturé (qui ne compte pas dans le groupe apparié, donc le numéro de groupement commence à partir du premier groupe capturé et non le non capturé), de sorte que la répétition du résultat du match-group(?:animal)
ne peut pas être appelé plus tard dans le code.J'espère que cela explique l'utilisation du groupe non capturant.
la source
Les groupes qui vous capturent peuvent être utilisés plus tard dans l'expression régulière pour correspondre OU vous pouvez les utiliser dans la partie de remplacement de l'expression régulière. Faire un groupe non capturant exempte simplement ce groupe d'être utilisé pour l'une ou l'autre de ces raisons.
Les groupes sans capture sont parfaits si vous essayez de capturer beaucoup de choses différentes et qu'il y a certains groupes que vous ne voulez pas capturer.
C'est à peu près la raison pour laquelle ils existent. Pendant que vous apprenez les groupes, découvrez les groupes atomiques , ils font beaucoup! Il existe également des groupes de contournement, mais ils sont un peu plus complexes et peu utilisés.
Exemple d'utilisation plus tard dans l'expression régulière (référence arrière):
<([A-Z][A-Z0-9]*)\b[^>]*>.*?</\1>
[Recherche une balise xml (sans support ns)]([A-Z][A-Z0-9]*)
est un groupe de capture (dans ce cas, c'est la variable)Plus tard dans l'expression régulière,
\1
cela signifie qu'il ne correspondra qu'au même texte que celui du premier groupe (le([A-Z][A-Z0-9]*)
groupe) (dans ce cas, il correspond à la balise de fin).la source
Eh bien, je suis un développeur JavaScript et j'essaierai d'expliquer son importance en ce qui concerne JavaScript.
Considérez un scénario dans lequel vous souhaitez faire correspondre
cat is animal
lorsque vous souhaitez faire correspondre chat et animal et que les deux devraient avoir unis
entre eux.la source
Dans les expressions régulières complexes, vous pouvez avoir la situation où vous souhaitez utiliser un grand nombre de groupes dont certains sont là pour la correspondance de répétition et dont certains sont là pour fournir des références en arrière. Par défaut, le texte correspondant à chaque groupe est chargé dans le tableau de référence arrière. Lorsque nous avons beaucoup de groupes et que nous devons seulement pouvoir en référencer certains à partir du tableau de référence arrière, nous pouvons remplacer ce comportement par défaut pour indiquer à l'expression régulière que certains groupes ne sont là que pour la gestion des répétitions et n'ont pas besoin d'être capturés et stockés dans le tableau de référence arrière.
la source
Je ne peux pas commenter les meilleures réponses pour dire ceci: je voudrais ajouter un point explicite qui n'est implicite que dans les meilleures réponses:
Le groupe non capturant
(?...)
ne supprime aucun caractère de la correspondance complète d'origine, il réorganise uniquement l'expression rationnelle visuellement au programmeur.Pour accéder à une partie spécifique de l'expression régulière sans caractères étrangers définis, vous devez toujours utiliser
.group(<index>)
la source
Les groupes non capturants tl; dr , comme leur nom l'indique, sont les parties de l'expression régulière que vous ne souhaitez pas inclure dans la correspondance et
?:
constituent un moyen de définir un groupe comme étant non capturant.Disons que vous avez une adresse e-mail
[email protected]
. L'expression régulière suivante créera deux groupes , la partie id et la partie @ example.com.(\p{Alpha}*[a-z])(@example.com)
. Par souci de simplicité, nous extrayons le nom de domaine entier, y compris le@
caractère.Maintenant, disons, vous n'avez besoin que de la partie id de l'adresse. Ce que vous voulez faire, c'est saisir le premier groupe du résultat du match, entouré par
()
l'expression régulière et la façon de le faire est d'utiliser la syntaxe de groupe non capturante, c'est-à-dire?:
. Ainsi, l'expression régulière(\p{Alpha}*[a-z])(?:@example.com)
ne renverra que la partie id de l'e-mail.la source
Une chose intéressante que j'ai rencontrée est le fait que vous pouvez avoir un groupe de capture à l'intérieur d'un groupe non-capture. Jetez un œil à l'expression rationnelle ci-dessous pour faire correspondre les URL Web:
Chaîne d'URL d'entrée:
Le premier groupe de mon expression régulière
(?:([A-Za-z]+):)
est un groupe non capturant qui correspond au schéma de protocole et au:
caractère deux-points , c'est-à-dire,http:
mais lorsque j'exécutais sous le code, je voyais que le 1er index du tableau renvoyé contenait la chaînehttp
lorsque je pensais celahttp
et deux points:
les deux ne seront pas signalés car ils font partie d'un groupe non capturant.J'ai pensé que si le premier groupe
(?:([A-Za-z]+):)
est un groupe non capturant, alors pourquoi il renvoie unehttp
chaîne dans le tableau de sortie.Donc, si vous remarquez qu'il y a un groupe imbriqué
([A-Za-z]+)
dans le groupe non capturant. Ce groupe imbriqué([A-Za-z]+)
est un groupe de capture (n'ayant pas?:
au début) en lui-même à l'intérieur d'un groupe non-capture(?:([A-Za-z]+):)
. C'est pourquoi le texte esthttp
toujours capturé, mais le:
caractère deux-points qui se trouve à l'intérieur du groupe de non-capture mais à l'extérieur du groupe de capture n'est pas signalé dans le tableau de sortie.la source
Ouvrez vos devTools Google Chrome, puis l'onglet Console: et saisissez ceci:
Exécutez-le et vous verrez:
Le
JavaScript
moteur RegExp capture trois groupes, les éléments avec les index 1,2,3. Utilisez maintenant une marque non capturante pour voir le résultat.Le résultat est:
C'est évident ce qui n'est pas le groupe de capture.
la source
Je pense que je vous donnerais la réponse. N'utilisez pas de variables de capture sans vérifier que la correspondance a réussi.
Les variables de capture
$1
, etc. ne sont valides que si la correspondance a réussi et ne sont pas non plus effacées.Dans l'exemple ci-dessus, pour éviter de capturer bronto
$1
,(?:)
est utilisé.Si le motif est apparié, il
$1
est capturé comme motif groupé suivant.Ainsi, la sortie sera comme ci-dessous:
Il est utile si vous ne souhaitez pas enregistrer les correspondances.
la source
C'est extrêmement simple, nous pouvons comprendre avec un exemple de date simple, supposons que si la date est mentionnée comme 1er janvier 2019 ou 2 mai 2019 ou toute autre date et nous voulons simplement la convertir au format jj / mm / aaaa , nous n'aurions pas besoin du mois nom qui est janvier ou février d'ailleurs, afin de capturer la partie numérique, mais pas le suffixe (facultatif), vous pouvez utiliser un groupe non capturant.
de sorte que l'expression régulière serait,
C'est aussi simple que ça.
la source