Java正则表达式替换为捕获组


76

有什么方法可以用捕获组的已修改内容替换正则表达式?

例:

Pattern regex = Pattern.compile("(\\d{1,2})");
Matcher regexMatcher = regex.matcher(text);
resultString = regexMatcher.replaceAll("$1"); // *3 ??

我想用$ 1乘以3代替所有出现的情况。

编辑:

看起来好像出了点问题:(

如果我用

Pattern regex = Pattern.compile("(\\d{1,2})");
Matcher regexMatcher = regex.matcher("12 54 1 65");
try {
    String resultString = regexMatcher.replaceAll(regexMatcher.group(1));
} catch (Exception e) {
    e.printStackTrace();
}

引发IllegalStateException:找不到匹配项

Pattern regex = Pattern.compile("(\\d{1,2})");
Matcher regexMatcher = regex.matcher("12 54 1 65");
try {
    String resultString = regexMatcher.replaceAll("$1");
} catch (Exception e) {
    e.printStackTrace();
}

工作正常,但我不能更改$ 1 :(

编辑:

现在,它正在工作:)


通过直接在弦上工作,我们终于有了
Aquarius Power

Answers:


80

怎么样:

if (regexMatcher.find()) {
    resultString = regexMatcher.replaceAll(
            String.valueOf(3 * Integer.parseInt(regexMatcher.group(1))));
}

要获得第一场比赛,请使用#find()。之后,您可以#group(1)用来引用该第一个匹配项,并将所有匹配项替换为第一个匹配值乘以3。

如果您想将每个匹配项替换为该匹配项的值乘以3:

    Pattern p = Pattern.compile("(\\d{1,2})");
    Matcher m = p.matcher("12 54 1 65");
    StringBuffer s = new StringBuffer();
    while (m.find())
        m.appendReplacement(s, String.valueOf(3 * Integer.parseInt(m.group(1))));
    System.out.println(s.toString());

您可能需要查看Matcher的文档,其中详细介绍了更多内容。


9
是的,但是您丢失了原始字符串。如果它是“ a 1 2 3”,则不会有a
Jasper

20
这很有帮助!另外一个补充是,如果您匹配的文本不匹配并且您的匹配项没有结尾,则需要调用m.appendTail(s);。
mezzie 2011年

查找周围带有静态文本(例如Pattern.compile(“ var myVar = \”(。*)\“;”);)的组时要小心。-它将替换所有找到的不仅是组。又见约翰O.的链接
曼努埃尔·曼哈特

@ManuelM。您可以通过使用肯定的先行和后向断言而不是静态文本来轻松忽略该问题。这样,这些部分将不会被匹配器替换。
klaar

感谢您的出色回答,您摘录了该价值乘数示例中最有用的部分!这对我来说很清楚!@mezzie很好!尽管Java文档中存在java.util.regex.Matcher,但对于仅参考此SO帖子的人来说,它将非常有帮助。:)
varun

11

伯爵的答案为您提供了解决方案,但我想我要补充一下造成您问题的原因IllegalStateException。您group(1)无需先调用匹配操作(例如find())就可以进行调用。如果您只是在使用$1replaceAll()则不需要此操作,因为这是匹配操作。


5

Java 9提供了一个Matcher.replaceAll()接受替换功能的:

resultString = regexMatcher.replaceAll(
        m -> String.valueOf(Integer.parseInt(m.group()) * 3));

1

资料来源:java-implementation-of-rubys-gsub

用法:

// Rewrite an ancient unit of length in SI units.
String result = new Rewriter("([0-9]+(\\.[0-9]+)?)[- ]?(inch(es)?)") {
    public String replacement() {
        float inches = Float.parseFloat(group(1));
        return Float.toString(2.54f * inches) + " cm";
    }
}.rewrite("a 17 inch display");
System.out.println(result);

// The "Searching and Replacing with Non-Constant Values Using a
// Regular Expression" example from the Java Almanac.
result = new Rewriter("([a-zA-Z]+[0-9]+)") {
    public String replacement() {
        return group(1).toUpperCase();
    }
}.rewrite("ab12 cd efg34");
System.out.println(result);

实施(重新设计):

import static java.lang.String.format;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class Rewriter {
    private Pattern pattern;
    private Matcher matcher;

    public Rewriter(String regularExpression) {
        this.pattern = Pattern.compile(regularExpression);
    }

    public String group(int i) {
        return matcher.group(i);
    }

    public abstract String replacement() throws Exception;

    public String rewrite(CharSequence original) {
        return rewrite(original, new StringBuffer(original.length())).toString();
    }

    public StringBuffer rewrite(CharSequence original, StringBuffer destination) {
        try {
            this.matcher = pattern.matcher(original);
            while (matcher.find()) {
                matcher.appendReplacement(destination, "");
                destination.append(replacement());
            }
            matcher.appendTail(destination);
            return destination;
        } catch (Exception e) {
            throw new RuntimeException("Cannot rewrite " + toString(), e);
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(pattern.pattern());
        for (int i = 0; i <= matcher.groupCount(); i++)
            sb.append(format("\n\t(%s) - %s", i, group(i)));
        return sb.toString();
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.