在Java中使用.*的Regexp分组和replaceAll复制替换

Uni*_*dow 5 java regex

我在Java中使用Rexexp时遇到了问题.示例代码写出来ABC_012_suffix_suffix,我期待它输出ABC_012_suffix

    Pattern rexexp  = Pattern.compile("(.*)");
    Matcher matcher = rexexp.matcher("ABC_012");
    String  result  = matcher.replaceAll("$1_suffix");

    System.out.println(result);
Run Code Online (Sandbox Code Playgroud)

我知道replaceAll会替换所有匹配的组,问题是为什么这个regexp组在Java中的(.*)字符串上匹配两次ABC_012

And*_*s_D 6

Pattern regexp  = Pattern.compile(".*");
Matcher matcher = regexp.matcher("ABC_012");
matcher.matches();
System.out.println(matcher.group(0));
System.out.println(matcher.replaceAll("$0_suffix"));
Run Code Online (Sandbox Code Playgroud)

同样发生在这里,输出是:

ABC_012
ABC_012_suffix_suffix
Run Code Online (Sandbox Code Playgroud)

原因隐藏在replaceAll方法中:它尝试find匹配模式的所有子序列:

while (matcher.find()) {
  System.out.printf("Start: %s, End: %s%n", matcher.start(), matcher.end());
}
Run Code Online (Sandbox Code Playgroud)

这将导致:

Start: 0, End: 7
Start: 7, End: 7
Run Code Online (Sandbox Code Playgroud)

所以,对我们的第一个惊喜,匹配器找到两个子序列,"ABC_012"另一个"".它附加"_suffix"到他们两个:

"ABC_012" + "_suffix" + "" + "_suffix"
Run Code Online (Sandbox Code Playgroud)


Ale*_*kov 5

可能.*会给你"完全匹配",然后减少与"空匹配"的匹配(但仍然匹配).尝试(.+)(^.*$)改为.两者都按预期工作.

在regexinfo星的定义如下:

*(星号) - 重复前一项零次或多次.贪婪,因此在尝试使用前一项的较少匹配的排列之前将匹配尽可能多的项目,直到前一项目根本不匹配的点.