Java替换所有反向引用

Wej*_*ejn 7 java regex replaceall

可能重复:
String.replaceAll()异常与正则表达式中的贪心量词

我正在编写使用的代码,Matcher#replaceAll并发现以下结果非常令人困惑:

Pattern.compile("(.*)").matcher("sample").replaceAll("$1abc");
Run Code Online (Sandbox Code Playgroud)

现在,我希望输出可以,sampleabc但Java会引发我的注意sampleabcabc.

有人有什么想法吗?

现在,当然,当我锚定模式(^(.*)$)时,问题就消失了.我仍然不知道为什么地狱会replaceAll做那样的双重替换.

并加上侮辱伤害,遵循以下代码:

Pattern.compile("(.*)").matcher("sample").replaceFirst("$1abc")
Run Code Online (Sandbox Code Playgroud)

按预期工作,只返回sampleabc.

Jon*_*eet 5

由于某种原因,它看起来像输入末尾的空字符串匹配.(我可以看出为什么会匹配;我很感兴趣它只匹配一次而且只有一次.)

如果replaceAll("$1abc")改为replaceAll("'$1'abc")结果是'sample'abc''abc.

请注意,如果您更改(.*)(.+)然后它可以正常工作,因为它必须匹配至少一个字符.

该代码确认诊断:

Matcher matcher = Pattern.compile("(.*)").matcher("sample");

while (matcher.find()) {
    System.out.printf("%d to %d\r\n", 
                      matcher.start(), 
                      matcher.end());
}
Run Code Online (Sandbox Code Playgroud)

......哪个输出:

0 to 6
6 to 6
Run Code Online (Sandbox Code Playgroud)


And*_*ark 5

这里有两件事可以解释为什么会发生这种情况:

  • (.*) 将成功匹配空字符串.
  • 比赛成功后,将在上一场比赛结束后的另一场比赛中尝试一个位置.

因此,在"sample"匹配整个字符串之后,在该字符串之后尝试另一个匹配e.即使没有剩下的字符,匹配也会成功,并且会发生第二次替换.

由于正则表达式引擎将始终向前移动,因此不会发生其他替换.在最后一个字符是有效的起始索引之后,空字符串将匹配一次,但在匹配空字符串之后,正则表达式引擎没有更多有效的起始位置来尝试匹配.

作为向正则表达式添加字符串锚的开头的替代方法,您可以修改正则表达式,使其通过更改(.*)为匹配一个或多个字符(.+).