Recherche…


Groupes de capture de base

Un groupe est une section d'une expression régulière entre parenthèses () . Ceci est communément appelé "sous-expression" et répond à deux objectifs:

  • Il rend la sous-expression atomique, c'est-à-dire qu'elle correspondra, échouera ou se répètera dans son ensemble.
  • La partie du texte correspondante est accessible dans le reste de l'expression et dans le reste du programme.

Les groupes sont numérotés dans les moteurs de regex, en commençant par 1. Traditionnellement, le nombre maximal de groupes est de 9, mais de nombreuses variantes de regex modernes prennent en charge des nombres de groupes plus élevés. Le groupe 0 correspond toujours au modèle entier, de la même manière que l'entière expression entière entre parenthèses.

Le nombre ordinal augmente à chaque parenthèse d'ouverture, que les groupes soient placés l'un après l'autre ou imbriqués:

foo(bar(baz)?) (qux)+|(bla)
   1   2       3      4

les groupes et leurs nombres

Après qu'une expression ait atteint une correspondance globale, tous ses groupes seront utilisés - qu'un groupe particulier ait réussi ou non à correspondre.

Un groupe peut être facultatif, comme (baz)? ci-dessus, ou dans une autre partie de l'expression qui n'a pas été utilisée pour la correspondance, comme (bla) ci-dessus. Dans ces cas, les groupes qui ne correspondent pas ne contiennent tout simplement aucune information.

Si un quantificateur est placé derrière un groupe, comme dans (qux)+ ci-dessus, le nombre total de groupes de l'expression reste le même. Si un groupe correspond à plusieurs fois, son contenu sera la dernière occurrence de correspondance. Cependant, les saveurs regex modernes permettent d'accéder à toutes les occurrences de sous-correspondance.


Si vous souhaitez récupérer la date et le niveau d'erreur d'une entrée de journal comme celle-ci:

2012-06-06 12:12.014 ERROR: Failed to connect to remote end

Vous pourriez utiliser quelque chose comme ceci:

^(\d{4}-\d{2}-\d{2}) \d{2}:\d{2}.\d{3} (\w*): .*$

Cela extraira la date de l'entrée de journal 2012-06-06 tant que groupe de capture 1 et le niveau d' ERROR tant que groupe de capture 2.

Références et groupes non capturés

Étant donné que les groupes sont "numérotés", certains moteurs prennent également en charge la correspondance avec ce qu’un groupe a précédemment mis en correspondance.

En supposant que vous vouliez correspondre à quelque chose où deux chaînes de longueur égale trois sont divisées par un $ vous utiliseriez:

(.{3})\$\1

Cela correspondrait à l'une des chaînes suivantes:

"abc$abc"
"a b$a b"
"af $af "
"   $   "

Si vous souhaitez qu'un groupe ne soit pas numéroté par le moteur, vous pouvez le déclarer non capturé. Un groupe non capturant ressemble à ceci:

(?:)

Ils sont particulièrement utiles pour répéter un certain nombre de fois, car un groupe peut également être utilisé comme "atome". Considérer:

(\d{4}(?:-\d{2}){2} \d{2}:\d{2}.\d{3}) (.*)[\r\n]+\1 \2

Cela correspondra à deux entrées de journalisation dans les lignes adjacentes ayant le même horodatage et la même entrée.

Groupes de capture nommés

Certaines variantes d'expression rationnelle permettent des groupes de capture nommés . Au lieu d'un index numérique, vous pouvez vous référer à ces groupes par leur nom dans le code suivant, c'est-à-dire dans les backreferences, dans le pattern replace et dans les lignes suivantes du programme.

Les index numériques changent au fur et à mesure que le nombre ou la disposition des groupes dans une expression change, de sorte qu'ils sont plus fragiles en comparaison.

Par exemple, pour faire correspondre un mot ( \w+ ) entre guillemets simples ou doubles ( ['"] ), nous pourrions utiliser:

(?<quote>['"])\w+\k{quote}

Ce qui équivaut à:

(['"])\w+\1

Dans une situation simple comme celle-ci, un groupe de capture numéroté régulier ne présente aucun inconvénient.

Dans des situations plus complexes, l'utilisation de groupes nommés rendra la structure de l'expression plus évidente pour le lecteur, ce qui améliorera la maintenabilité.

L'analyse de fichier journal est un exemple d'une situation plus complexe qui tire parti des noms de groupe. Voici le format de journal commun Apache (CLF):

127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326

L'expression suivante capture les parties dans des groupes nommés:

(?<ip>\S+) (?<logname>\S+) (?<user>\S+) (?<time>\[[^]]+\]) (?<request>"[^"]+") (?<status>\S+) (?<bytes>\S+)

La syntaxe dépend de la saveur, les plus courantes sont:

  • (?<name>...)
  • (?'name'...)
  • (?P<name>...)

Références:

  • \k<name>
  • \k{name}
  • \k'name'
  • \g{name}
  • (?P=name)

Dans l'arôme .NET, plusieurs groupes peuvent partager le même nom, ils utiliseront des piles de capture .

Dans PCRE, vous devez l'activer explicitement en utilisant le modificateur (?J) ( PCRE_DUPNAMES ) ou en utilisant le groupe de réinitialisation de branche (?|) . Seule la dernière valeur capturée sera accessible.

(?J)(?<a>...)(?<a>...)
(?|(?<a>...)|(?<a>...))


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow