Ssortingng.replaceAll (regex) effectue le même remplacement deux fois

Quelqu’un peut-il me dire pourquoi

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

Résulte en

 aa 

Notez que ce qui suit a le même résultat:

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

Je l’ai testé sur java 6 et 7 et les deux semblent se comporter de la même manière. Est-ce que je manque quelque chose ou est-ce un bug dans le moteur de regex java?

Ce n’est pas une anomalie:. .* Peut correspondre à n’importe quoi.

Vous demandez à remplacer toutes les occurrences:

  • la première occurrence correspond à la chaîne entière, le moteur de regex commence donc à la fin de la saisie pour la prochaine correspondance;
  • mais .* correspond également à une chaîne vide! Il correspond donc à une chaîne vide à la fin de l’entrée et la remplace par a .

Utiliser à la place .+ Ne présentera pas ce problème car cette regex ne peut pas correspondre à une chaîne vide (il faut au moins un caractère pour correspondre).

Ou, utilisez .replaceFirst() pour ne remplacer que la première occurrence:

 "test".replaceFirst(".*", "a") ^^^^^^^^^^^^ 

Maintenant, pourquoi .* Se comporte comme il le fait et ne correspond pas plus de deux fois (cela pourrait théoriquement le faire) 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 ssortingng, 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 @AH le note dans les commentaires, tous les moteurs de regex ne se comportent pas de cette façon. GNU sed par exemple, considérera qu’il a épuisé les données après la première correspondance.