web-dev-qa-db-fra.com

Java regex capturant des index de groupes

J'ai la ligne suivante,

typeName="ABC:xxxxx;";

J'ai besoin d'aller chercher le mot ABC,

J'ai écrit l'extrait 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) j'obtiens ABC: mais si je mets group(1) c'est ABC, alors je veux savoir

  1. Que signifie 0 et 1? Ce sera mieux si quelqu'un peut m'expliquer avec de bons exemples.

  2. Le modèle de regex contient un :, alors pourquoi group(1) le résultat l'omet? Le groupe 1 détecte-t-il tous les mots entre parenthèses?

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

L'extrait de code a été donné dans le but de dissiper mes confusions. Ce n'est pas le code que je traite. Le code donné ci-dessus peut être fait avec String.split() d'une manière beaucoup plus simple.

108
P basak

Capture et regroupement

Groupe de capture(pattern) crée un groupe doté de la propriété capturing.

Une propriété apparentée que vous pouvez souvent voir (et utiliser) est (?:pattern), qui crée une propriété groupe sans capture, d'où le nom non capturant]. groupe.

Un groupe est généralement utilisé lorsque vous devez répéter une séquence de motifs, par ex. (\.\w+)+, ou pour spécifier l'endroit où l'alternance doit prendre effet, par ex. ^(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, en dehors du groupe, enregistre également le texte correspondant au motif à l'intérieur du groupe de capture (pattern). En utilisant votre exemple, (.*):, .* correspond à ABC et : correspond à :, et puisque .* fait partie du groupe de capture (.*). , le texte ABC est enregistré pour le groupe de capture 1.

Numéro de groupe

Le modèle entier est défini pour être le numéro de groupe 0.

Tout groupe de capture du modèle commence à indexer à partir de 1. Les indices sont définis par l'ordre des parenthèses d'ouverture des groupes de capture . À titre d’exemple, voici all 5 groupes de capture dans le modèle 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 la référence arrière \n dans le modèle et $n dans la chaîne de remplacement.

Dans d'autres types de regex (PCRE, Perl), ils peuvent également être utilisés dans appels de sous-routine.

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

Dans certains types d’expression regex (PCRE, Perl), il existe une fonction branche réinitialisée qui vous permet d’utiliser le même nombre pour capturant des groupes dans différentes branches d'alternance .

Nom de groupe

À partir de Java 7, vous pouvez définir un groupe de capture nommé(?<name>pattern) et accéder au contenu correspondant à Matcher.group(String name) . La regex est plus longue, mais le code est plus significatif, car il indique ce que vous essayez de faire correspondre ou d'extraire avec la regex.

Les noms de groupe sont utilisés dans la référence arrière \k<name> dans le modèle et ${name} dans la chaîne de remplacement.

Les groupes de capture nommés sont toujours numérotés avec le même schéma de numérotation. Ils sont donc également accessibles via Matcher.group(int group).

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

173
nhahtdh

Pour le reste de nous

Voici un exemple simple et clair de la façon dont cela fonctionne

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 constater, j’ai créé CINQ groupes, chacun entre parenthèses.

J'ai inclus le! * Et *! de chaque côté pour le rendre plus clair. Notez qu'aucun de ces caractères ne se trouve dans le RegEx et ne sera donc pas généré dans les résultats. Groupe (0) vous donne simplement toute la chaîne correspondante (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 des espaces blancs, qui dans ce cas sont littéralement des caractères d'espaces, mais pourraient également être des tabulations ou des sauts de ligne, etc. Le groupe 3 inclut l'espace parce que je le mets dans les critères de recherche ... etc.

J'espère que cela a du sens.

87
Michael Sims

Les parenthèses () permettent d'activer le regroupement de phrases d'expression rationnelle.

La group(1) contient la chaîne entre parenthèses (.*) so .* dans ce cas

Et group(0) contient toute la chaîne correspondante.

Si vous aviez plus de groupes (lisez (...)), il serait placé dans des groupes avec les prochains index (2, 3, etc.).

44
Michal Borek