41 votes

Chaîne de caractères.replaceAll() anomalie gourmand avec des quantificateurs dans les regex

Quelqu'un peut me dire pourquoi

System.out.println("test".replaceAll(".*", "a"));

Résultats dans

aa

Notez que celui-ci a le même résultat:

System.out.println("test".replaceAll(".*$", "a"));

J'ai testé cela sur java 6 et 7 et les deux semblent se comporter de la même manière. Ai-je raté quelque chose ou est-ce un bug dans le moteur d'expressions régulières java?

60voto

fge Points 40850

Ce n'est pas une anomalie: .* peut correspondre à quoi que ce soit.

Vous vous demandez pour remplacer toutes les occurrences:

  • la première occurrence correspond à l'ensemble de la chaîne, le moteur d'expressions régulières commence donc à partir de la fin de l'entrée pour le prochain match;
  • mais .* correspond à une chaîne vide! Par conséquent, elle correspond à une chaîne vide à la fin de la saisie, et le remplace par a.

À l'aide de .+ plutôt présentent pas ce problème car cette expression ne peut pas correspondre à une chaîne vide (il faut au moins un caractère de correspondance).

Alors, pourquoi est - .* se comporte comme il le fait et ne correspond pas à plus de deux fois (il pourrait théoriquement) est une chose intéressante à considérer. Voir ci-dessous:

# Before first run
regex: |.*
input: |whatever
# After first run
regex: .*|
input: whatever|
#before second run
regex: |.*
input: whatever|
#after second run: since .* can match an empty string, it it satisfied...
regex: .*|
input: whatever|
# However, this means the regex engine matched an empty input.
# All regex engines, in this situation, will shift
# one character further in the input.
# So, before third run, the situation is:
regex: |.*
input: whatever<|ExhaustionOfInput>
# Nothing can ever match here: out

Notez que, comme @A. H. notes dans les commentaires, pas tous les regex moteurs se comportent de cette façon. GNU sed , par exemple, considèrent qu'il a épuisé l'entrée après le premier match.

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