Étrange problème avec `(. *) *`, `(. *) +`, `(. +) *` Dans Java regex

Afin de reproduire le problème comme indiqué dans une question récente – Pourquoi (. *) * Effectue-t-il deux correspondances et ne sélectionne-t-il rien dans le groupe $ 1? J’ai essayé diverses combinaisons de * et + , à l’intérieur et à l’extérieur des crochets, et le résultat obtenu n’était pas attendu.

Je me serais attendu au résultat, comme celui expliqué dans la réponse acceptée dans cette question, et dans une autre question dupliquée, étiquetée sous Perl – Pourquoi le. * Ne consum – t-il pas la chaîne entière dans cette expression rationnelle Perl? . Mais cela ne se comporte pas de la même manière.

Pour simplifier les choses, voici le code que j’ai essayé: –

 Ssortingng str = "input"; Ssortingng[] patterns = { "(.*)*", "(.*)+", "(.+)*", "(.+)+" }; for (Ssortingng pattern: patterns) { Matcher matcher = Pattern.comstack(pattern).matcher(str); while (matcher.find()) { System.out.print("'" + matcher.group(1) + "' : '" + matcher.start() + "'" + "\t"); } System.out.println(); } 

Et voici le résultat obtenu pour toutes les 4 combinaisons: –

 '' : '0' '' : '5' // For `(.*)*` '' : '0' '' : '5' // For `(.*)+` 'input' : '0' 'null' : '5' // For `(.+)*` 'input' : '0' // For `(.+)+` 

Maintenant, ce que je ne comprends pas, pourquoi dans les 1st et 2nd sorties, je ne reçois pas la chaîne entière comme first result pour matcher.find() . Je veux dire, idéalement, dans le 1er cas,. .* Devrait d’abord capturer la chaîne entière, puis capturer également la empty ssortingng à la fin. Maintenant, bien qu’il donne le résultat attendu pour le 2e match, il ne se comporte pas bien pour le 1st match .

Et aussi, dans le 2ème cas, je ne devrais même pas obtenir le 2ème match, car je dispose d’un quantificateur + dehors de la fourchette.

Ma sortie attendue est: –

 'input' : '0' '' : '5' // For 1st 'input' : '0' // For 2nd 

Aussi, dans la 3rd sortie, pourquoi est-ce que j’ai null comme 2ème correspondance au lieu de empty ssortingng ? Le 2ème match pour les 3 premières combinaisons ne devrait-il pas être identique?

La 4ème sortie est conforme aux attentes. Donc, pas de doute là-dessus.

Vous voyez l’effet du même phénomène que vous voyez dans la question à laquelle vous avez lié:

Pour (.*)* :

  • Le premier matcher.start() est 0 car c’est là que commence la correspondance ( "input" ).
  • Le premier matcher.group(1) est "" car le caractère répété (.*) remplacé la "input" capturée par la chaîne vide (mais matcher.group(0) contient une input" ).
  • Le second matcher.start() est 5 car c’est là que se trouve le moteur d’expression régulière après le premier match réussi.
  • Le second matcher.group(1) (ainsi que matcher.group(0) ) est "" parce que c’est tout ce qu’il y avait à faire à la fin de la chaîne.

Pour (.*)+ C’est pareil. Après tout, la chaîne vide peut être répétée autant de fois que vous le souhaitez et rest la chaîne vide.

Pour (.+)* Vous obtenez une valeur null car, si la deuxième correspondance est réussie (aucune répétition d’une chaîne de longueur égale à 1 ne correspond à la chaîne vide), les parenthèses capturées n’ont pas été capturées. Son contenu est donc null (comme dans non défini, au lieu de la chaîne vide).