Java 替换捕获组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2921212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 14:30:54  来源:igfitidea点击:

replace capturing group

javaregex

提问by Dónal

If I have a regex with a capturing group, e.g. foo(_+f). If I match this against a string and want to replace the first capturing group in all matcheswith bazso that

如果我有一个带有捕获组的正则表达式,例如foo(_+f). 如果我符合这个对一个字符串,要替换的第一个捕获组中的所有比赛baz使

foo___f blah foo________f

is converted to:

转换为:

foobaz blah foobaz

There doesn't appear to be any easy way to do this using the standard libraries. If I use Matcher.replaceAll()this will replace all matches of the entire pattern and convert the string to

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

baz blah baz

Obviously I can just iterate through the matches, store the start and end index of each capturing group, then go back and replace them, but is there an easier way?

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

Thanks, Don

谢谢,唐

采纳答案by polygenelubricants

I think you want something like this?

我想你想要这样的东西?

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

Here you simply replace the entire match with "baz", but the match uses lookbehind to ensure that _+fis preceded by foo.

在这里,您只需将整个匹配替换为"baz",但匹配使用后视来确保_+f前面是foo

See also

也可以看看



If lookbehind is not possible (perhaps because the length is not finite), then simply capture even what you're NOT replacing, and refer to them back in the replacement string.

如果后视是不可能的(可能是因为长度不是有限的),那么只需捕获您没有替换的内容,然后在替换字符串中将它们引用回来。

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

So here we're effectively only replacing what \2matches.

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

回答by Amarghosh

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

回答by Kennet

Is this anywhere close ....

这是附近的任何地方吗....

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

Ie, add a capturing group for 'foo' also. Otherwise a simple replacement would be

即,也为“foo”添加一个捕获组。否则一个简单的替换将是

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

回答by Bryce Sandlund

So I don't think any of these answers do justice to more abstract cases of the following question, which is something I ran into myself, so I wrote some code that works in the more general case:

所以我认为这些答案中的任何一个都不能正确处理以下问题的更抽象的情况,这是我自己遇到的问题,所以我编写了一些适用于更一般情况的代码:

/**
 * 
 * @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);
}

On your example, it does precisely as you describe:

在您的示例中,它完全按照您的描述执行:

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

Prints out:

打印出来:

foobaz blah foobaz