无法理解String.replaceAll非贪婪的行为

eke*_*ren 6 java regex

可能重复:
Java正则表达式异常?

任何想法为什么以下测试失败(返回"xx"而不是"x")

@Test 
public void testReplaceAll(){
    assertEquals("x", "xyz".replaceAll(".*", "x"));
}
Run Code Online (Sandbox Code Playgroud)

我不想这样做"^.*$"......我想了解这种行为.任何线索?

fge*_*fge 9

是的,它与此问题中描述的完全相同!

.* 将首先匹配整个输入,但在输入结束时也是一个空字符串...

让我们在您的示例中使用|和输入来表示正则表达式引擎<...>.

  • 输入:<xyz>;
  • 正则表达式引擎,在第一次运行之前:<|xyz>;
  • 正则表达式引擎,首次运行后:( <xyz|>匹配文本:"xyz");
  • 正则表达式引擎,第二次运行后:( <xyz>|匹配文本:"").

并非所有正则表达式引擎都以这种方式运行.但是Java确实如此.perl也是如此.作为反例,Sed将在步骤3中输入结束后定位其光标.

现在,您还必须了解一个关键的事情:正则表达式引擎,当遇到零长度匹配时,总是提前一个字符.否则,请考虑如果您尝试将'^'替换为'a'会发生什么:'^'匹配位置,因此是零长度匹配.如果引擎没有前进一个字符,则"x"将替换为"ax",这将替换为"aax"等.因此,在第二个匹配(空的)之后,Java的正则表达式引擎会提前一个"字符" "......其中没有:处理结束.