119 votes

Java regex index de groupes de capture

Je possède la ligne suivante,

typeName="ABC:xxxxx;";

J'ai besoin de récupérer le mot ABC,

J'ai écrit le bout de code suivant,

Pattern pattern4=Pattern.compile("(.*):");
matcher=pattern4.matcher(typeName);

String nameStr="";
if(matcher.find())
{
    nameStr=matcher.group(1);

}

Donc si je mets group(0) je reçois ABC: mais si je mets group(1) c'est ABC, donc je veux savoir

  1. Que signifient ces 0 et 1? Ce serait mieux si quelqu'un pouvait m'expliquer avec de bons exemples.

  2. Le motif regex contient un :, alors pourquoi le résultat de group(1) omet cela? Est-ce que le groupe 1 détecte tous les mots à l'intérieur des parenthèses?

  3. Donc, si je mets deux parenthèses de plus comme ceci, \\s*(\d*)(.*): alors, y aura-t-il deux groupes? group(1) renverra la partie (\d*) et group(2) renverra la partie (.*)?

Le bout de code était donné dans le but de dissiper mes confusions. Ce n'est pas le code avec lequel je travaille. Le code donné ci-dessus peut être fait avec String.split() de manière beaucoup plus simple.

187voto

nhahtdh Points 28167

Capturer et grouper

Groupe de capture (pattern) crée un Groupe qui a une propriété de capture.

Un autre groupe connexe que vous pourriez souvent voir (et utiliser) est (?:pattern), qui crée un Groupe sans propriété de capture, donc nommé Groupe non capturant.

Un groupe est généralement utilisé lorsque vous avez besoin de répéter une séquence de motifs, par exemple (\.\w+)+, ou pour spécifier où l'alternance doit prendre effet, par exemple ^(0*1|1*0)$ (^, puis 0*1 ou 1*0, puis $) versus ^0*1|1*0$ (^0*1 ou 1*0$).

Un groupe de capture, mis à part le groupement, enregistrera également le texte correspondant au motif à l'intérieur du groupe de capture (pattern). En utilisant votre exemple, (.*):, .* correspond à ABC et : correspond à :, et puisque .* est à l'intérieur du groupe de capture (.*), le texte ABC est enregistré pour le groupe de capture 1.

Numéro de groupe

L'ensemble du motif est défini comme étant le groupe numéro 0.

Tout groupe de capture dans le motif commence l'indexation à partir de 1. Les indices sont définis par l'ordre des parenthèses ouvrantes des groupes de capture. Par exemple, voici tous les 5 groupes de capture dans le motif ci-dessous:

(group)(?:non-capturing-group)(g(?:ro|u)p( (nested)inside)(another)group)(?=assertion)
|     |                       |          | |      |      ||       |     |
1-----1                       |          | 4------4      |5-------5     |
                              |          3---------------3              |
                              2-----------------------------------------2

Les numéros de groupe sont utilisés dans les back-references \n dans le motif et $n dans la chaîne de remplacement.

Dans d'autres variantes d'expressions régulières (PCRE, Perl), ils peuvent également être utilisés dans des appels de sous-routine.

Vous pouvez accéder au texte correspondant à un certain groupe avec Matcher.group(int group). Les numéros de groupe peuvent être identifiés avec la règle énoncée ci-dessus.

Dans certaines variantes d'expressions régulières (PCRE, Perl), il existe une fonctionnalité de réinitialisation de branche qui vous permet d'utiliser le même nombre pour les groupes de capture dans différentes branches d'alternance.

Nom de groupe

À partir de Java 7, vous pouvez définir un Groupe de capture nommé (?pattern), et vous pouvez accéder au contenu correspondant avec Matcher.group(String name). L'expression régulière est plus longue, mais le code est plus significatif, car il indique ce que vous essayez de faire correspondre ou d'extraire avec l'expression régulière.

Les noms de groupe sont utilisés dans les back-references \k dans le motif et ${name} dans la chaîne de remplacement.

Les groupes de capture nommés sont toujours numérotés selon le même schéma de numérotation, donc ils peuvent également être accédés via Matcher.group(int group).

En interne, l'implémentation de Java mappe simplement le nom sur le numéro de groupe. Par conséquent, vous ne pouvez pas utiliser le même nom pour 2 groupes de capture différents.

101voto

Michael Sims Points 1227

Pour le reste d'entre nous

Voici un exemple simple et clair de comment cela fonctionne:

( G1 )( G2 )( G3 )( G4 )( G5 )
Regex:([a-zA-Z0-9]+)([\s]+)([a-zA-Z ]+)([\s]+)([0-9]+)

Chaîne: "!* UserName10 John Smith 01123 *!"

group(0): UserName10 John Smith 01123
group(1): UserName10
group(2):  
group(3): John Smith
group(4):  
group(5): 01123

Comme vous pouvez le voir, j'ai créé CINQ groupes qui sont chacun inclus entre parenthèses.

J'ai inclus les !* et *! de chaque côté pour que ce soit plus clair. Notez que aucun de ces caractères ne figure dans l'expression régulière et par conséquent ne sera pas produit dans les résultats. Le groupe(0) vous donne simplement la chaîne correspondante complète (tous mes critères de recherche sur une seule ligne). Le groupe 1 s'arrête juste avant le premier espace car le caractère espace n'était pas inclus dans les critères de recherche. Les groupes 2 et 4 sont simplement les espaces blancs, qui dans ce cas sont littéralement un caractère espace, mais pourraient aussi être une tabulation ou un saut de ligne, etc. Le groupe 3 inclut l'espace car je l'ai mis dans les critères de recherche ... etc.

J'espère que cela est clair.

46voto

Michal Borek Points 3522

Les parenthèses () sont utilisées pour permettre le regroupement des expressions régulières.

Le group(1) contient la chaîne qui se trouve entre les parenthèses (.*) donc .* dans ce cas

Et group(0) contient l'ensemble de la chaîne correspondante.

Si vous aviez plus de groupes (lisez (...)), ils seraient mis dans des groupes avec les indexes suivants (2, 3, et ainsi de suite).

0voto

DeadlyJesus Points 512

À mon avis, utiliser String.split() rendrait les choses plus faciles.

String whatYouwant = typeName.split(":")[0];

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X