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

时间:2011-12-29 19:33:46

标签: java regex

  

可能重复:
  Java regex anomaly?

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

@Test 
public void testReplaceAll(){
    assertEquals("x", "xyz".replaceAll(".*", "x"));
}

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

2 个答案:

答案 0 :(得分:9)

是的,它与this question中描述的完全相同!

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

让我们用|表示正则表达式引擎,并在示例中用<...>表示输入。

  • 输入:<xyz>;
  • 正则表达式引擎,在首次运行之前:<|xyz>;
  • 正则表达式引擎,首次运行后:<xyz|>(匹配的文字:“xyz”);
  • 正则表达式引擎,在第二次运行后:<xyz>|(匹配的文字:“”)。

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

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

答案 1 :(得分:0)

@Test 
public void testReplaceAll(){
    assertEquals("x", "xyz".replaceAll(".+", "x"));
}

可能会这样做,因为它需要一个或更多字符,因此会阻止*可能匹配零个字符并将其替换为“x”的行为。