替换捕获组

如果我有一个带有捕获组的正则表达式,例如foo(_+f) 。 如果我将其与字符串匹配,并希望用baz替换所有匹配中的第一个捕获组以便这样做

 foo___f blah foo________f 

转换为:

 foobaz blah foobaz 

使用标准库似乎没有任何简单的方法。 如果我使用Matcher.replaceAll(),这将替换整个模式的所有匹配并将字符串转换为

 baz blah baz 

显然我可以迭代匹配,存储每个捕获组的开始和结束索引,然后返回并替换它们,但是有更简单的方法吗?

谢谢,唐

我想你想要这样的东西?

  System.out.println( "foo__f blah foo___f boo___f".replaceAll("(?<=foo)_+f", "baz") ); // prints "foobaz blah foobaz boo___f" 

在这里,您只需用"baz"替换整个匹配,但匹配使用lookbehind确保_+f前面有foo

也可以看看

  • regular-expressions.info/Lookarounds

如果无法实现lookbehind(可能因为长度不是有限的),那么只需捕获你不替换的内容,并在替换字符串中引用它们。

  System.out.println( "fooooo_f boooo_f xxx_f".replaceAll("(fo+|bo+)(_+f)", "$1baz") ); // prints "fooooobaz boooobaz xxx_f" 

所以这里我们实际上只是替换了\2匹配。

所以我认为这些答案中的任何一个都不能对下面问题的更抽象的案例做出公正的判断,这是我遇到的问题,所以我编写了一些在更一般的情况下工作的代码:

 /** * * @param regex Pattern to find in oldLine. Will replace contents in ( ... ) - group(1) - with newValue * @param oldLine Previous String that needs replacing * @param newValue Value that will replace the captured group(1) in regex * @return */ public static String replace(String regex, String oldLine, String newValue) { Pattern p = Pattern.compile(regex); Matcher m = p.matcher(oldLine); if (m.find()) { return m.replaceAll(replaceGroup(regex, newValue)); } else { throw new RuntimeException("No match"); } } /** * Replaces group(1) ( ... ) with replacement, and returns the resulting regex with replacement String * @param regex Regular expression whose parenthetical group will be literally replaced by replacement * @param replacement Replacement String * @return */ public static String replaceGroup(String regex, String replacement) { return regex.replaceAll("\\(.*\\)", replacement); } 

在您的示例中,它正如您所描述的那样:

 String regex = "foo(_+f)"; String line = "foo___f blah foo________f"; System.out.println(FileParsing.replace(regex, line, "baz")); 

打印出来:

 foobaz blah foobaz 
 p = Pattern.compile("foo(g.*?f)"); m = p.matcher("foog___f blah foog________f"); s = m.replaceAll("foobaz");//replace with foobaz instead of just baz System.out.println(s);//foobaz blah foobaz 

这有点接近……

 String[] s = {"foo___f blah foo________f", "foo___f blah goo________f"}; for(String ss: s) System.out.println(ss.replaceAll("(foo)(_+)f", "$1baz")); 

即,也为’foo’添加捕获组。 否则将进行简单的替换

 "foo___f blah foo________f".replaceAll("(_+)f", "baz")