String.replaceAll(正则expression式)进行两次相同的replace

谁能告诉我为什么

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

结果是

 aa 

请注意以下具有相同的结果:

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

我已经在java 6和7上testing过了,两者似乎都是一样的。 我错过了什么,或者这是一个在Java正则expression式引擎的错误?

这不是一个exception: .*可以匹配任何东西。

您要求更换所有事件:

  • 第一次匹配整个string,因此正则expression式引擎从下一次匹配的input结束开始;
  • 但是.*也匹配一个空string! 因此,它在input的末尾匹配空string,并用areplace。

使用.+而不会出现这个问题,因为这个正则expression式不能匹配一个空string(它至less需要一个字符匹配)。

或者,使用.replaceFirst()仅replace第一个匹配项:

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

现在,为什么.*performance得像它一样, 不匹配两次以上 (理论上可能)是一个有趣的事情要考虑。 见下文:

 # 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 

请注意,正如注释中的@AH注释,并非所有正则expression式引擎都以这种方式运行。 例如,GNU sed会认为它在第一场比赛后已经耗尽了input。