【问题标题】:can't understand String.replaceAll non-greedy behavior [duplicate]无法理解 String.replaceAll 非贪婪行为 [重复]
【发布时间】:2011-12-29 19:33:46
【问题描述】:

可能重复:
Java regex anomaly?

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

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

我不想做"^.*$".... 我想了解这种行为。 有什么线索吗?

【问题讨论】:

  • "xyz".replaceAll(".*", "x") 返回什么?
  • @JackEdmonds 为什么是"xx" 而不是"xxx"

标签: java regex


【解决方案1】:

是的,和this question中描述的完全一样!

.* 将首先匹配整个输入,然后在输入末尾匹配一个空字符串...

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

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

并非所有正则表达式引擎都以这种方式运行。然而,Java 确实如此。 perl 也是如此。作为反例,sed 会将其光标定位在第 3 步中输入的结尾之后。

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

【讨论】:

  • 但这不是贪婪匹配吗?
  • 嗯,它贪婪的,不是吗?请记住,* 表示“ 或更多”。所以,.* 对空字符串完全满意!
  • 在我理解的编辑之后——java迭代它的发现......当它到达最后一个字符时,它也会导致匹配(空字符匹配......)谢谢!!!跨度>
  • 查看编辑:这个例子还有一个非常重要的事情要理解。
【解决方案2】:
@Test 
public void testReplaceAll(){
    assertEquals("x", "xyz".replaceAll(".+", "x"));
}

可能会成功,因为这需要 一个 或更多字符,因此确实可以防止 * 可能匹配零个字符并将其替换为“x”的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    • 2013-02-04
    • 2011-08-25
    • 2016-09-05
    • 1970-01-01
    相关资源
    最近更新 更多