77 votes

Comment fait {m} {n} (« exactement n fois » deux fois) fonctionne ?

Donc, d'une manière ou d'une autre (à jouer), je me suis retrouvé avec une regex comme \d{1}{2}.

Logiquement, pour moi, il devrait dire:

(Un chiffre exactement une fois) exactement deux fois, c'est à dire un chiffre exactement deux fois.

Mais en effet, il semble juste de dire, "un chiffre exactement une fois" (ignorant ainsi l' {2}).

String regex = "^\\d{1}{2}$"; // ^$ to make those not familiar with 'matches' happy
System.out.println("1".matches(regex)); // true
System.out.println("12".matches(regex)); // false

Des résultats similaires peuvent être visibles à l'aide d' {n}{m,n} ou similaire.

Pourquoi est-ce arrivé? Il est explicitement indiqué dans la regex / documentation de Java quelque part ou est-ce juste un de décision des développeurs Java fait à la volée ou est-ce peut-être un bug?

Ou est-il en fait pas ignoré et il signifie en fait quelque chose de complètement différent?

Non pas que cela importe beaucoup, mais ce n'est pas la regex comportement, Rubular fait ce que j'attends.

Remarque - le titre est principalement pour la facilité de recherche pour les utilisateurs qui veulent savoir comment ça marche (pourquoi pas).

108voto

piet.t Points 4360

Standard IEEE 1003.1 dit :

Le comportement de plusieurs symboles de duplication adjacentes (' *' et intervalles) produit des résultats indéfinis.

Pour chaque application peut faire comme il lui plaît, juste ne reposent pas sur quelque chose de spécifique...

76voto

Lieven Keersmaekers Points 32396

Quand j'ai d'entrée de votre regex dans RegexBuddy en utilisant le Java syntaxe regex, il affiche le message suivant

Les quantificateurs doit être précédée par un jeton qui peut être répété «{2}»

Modification de l'expression régulière à utiliser explicitement un groupement ^(\d{1}){2} résout cette erreur et fonctionne comme prévu.


Je suppose que le moteur d'expressions régulières java simplement néglige l'erreur/l'expression et travaille avec ce qui a été compilées à ce jour.

Modifier

La référence à la Norme IEEE dans @piet.t la réponse semble appuyer cette hypothèse.

Edit 2 (bravo à @fncomp)

Pour être exhaustif, on peut normalement utiliser (?:)à éviter la capture du groupe. La regex complète devient alors ^(?:\d{1}){2}

10voto

Kobi Points 65357

Approche scientifique:
cliquez sur les modèles pour voir l'exemple sur regexplanet.com et cliquez sur le vert de Java bouton.

  • Vous avez déjà montré \d{1}{2} correspond "1", et ne correspond pas à "12", de sorte que nous savons qu'il n'est pas interprété en (?:\d{1}){2}.
  • Encore, 1 est un ennuyeux nombre et {1} peut être optimisé à l'écart, permet d'essayer quelque chose de plus intéressant:
    \d{2}{3}. Cela ne correspond à deux caractères (et non six), {3} est ignoré.
  • Ok. Il y a un moyen facile de voir ce qu'un moteur d'expressions régulières. Capturer?
    Permet d'essayer (\d{1})({2}). Bizarrement, cela fonctionne. Le deuxième groupe, $2, saisit une chaîne de caractères vide.
  • Alors, pourquoi avons-nous besoin de le premier groupe? Que diriez - ({1})? Fonctionne toujours.
  • Et juste {1}? Pas de problème.
    Il ressemble à Java est un peu bizarre ici.
  • Super! Donc, {1} est valide. Nous savons Java élargit * et + de {0,0x7FFFFFFF} et {1,0x7FFFFFFF}, donc, allons - * ou + travail? Non:

    Balançant méta caractère " + " à proximité de l'index 0
    +
    ^

    La validation doit venir avant * et + sont développées.

Je n'ai rien trouvé dans la spec qui explique que, il semble comme un quantificateur doit venir au moins d'après un personnage, des crochets ou des parenthèses.

La plupart de ces modèles sont considérés comme non valides par d'autres regex saveurs, et pour une bonne raison: ils ne font pas de sens.

4voto

jlordo Points 22012

Dans un premier temps, j’ai été surpris que cela ne jette pas un `` .

Je ne peux pas baser ma réponse sur tous les faits, c’est juste une supposition :

4voto

zb226 Points 2138

Je n’ai jamais vu la syntaxe n’importe où. Il semble que le moteur de regex sur cette page Rubular applique le quantificateur vers le plus petit jeton possible avant cela - qui est . Pour imiter cela en Java (ou la plupart des autres moteurs regex, il semblerait), vous devez regrouper les comme suit :

Voyez-le en action ici.

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