替换捕获组

时间:2010-05-27 12:50:53

标签: java regex

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

foo___f blah foo________f

转换为:

foobaz blah foobaz

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

baz blah baz

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

谢谢, 唐

4 个答案:

答案 0 :(得分:25)

我想你想要这样的东西?

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

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

另见


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

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

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

答案 1 :(得分:4)

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

/**
 * 
 * @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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

这是否接近......

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")