【问题标题】:How do you replace groups in a regular expression?如何替换正则表达式中的组?
【发布时间】:2014-01-25 17:14:48
【问题描述】:

究竟如何在将组附加到字符串缓冲区时替换组? 例如: (a)(b)(c) 如何用 d 替换第 1 组,用 e 替换第 2 组,依此类推? 我正在使用 Java 正则表达式引擎。 提前致谢。

【问题讨论】:

标签: java regex


【解决方案1】:

你可以使用Matcher'sappendReplacement

这是一个使用示例:

输入:“你好,鲍勃,你的猫怎么样?”

正则表达式:"(bob|cat)"

输出:“你好 alice,你的狗好吗”

public static void main(String[] args) {
    Pattern p = Pattern.compile("(bob|cat)");
    Matcher m = p.matcher("hello bob How is your cat?");
    StringBuffer s = new StringBuffer();
    while (m.find()) {
        m.appendReplacement(s, doReplace(m.group(1)));
    }
    m.appendTail(s);
    System.out.println(s.toString());
}


public static String doReplace(String s) {
    if(s.equals("bob")) {
        return "alice";
    }
    if(s.equals("cat")) {
        return "dog";
    }

    return "";
}

【讨论】:

  • +1,但您忘记通过调用 appendTail() 来完成它。我修好了。
【解决方案2】:

你在寻找这样的东西吗?

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

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

public class Program1 {
    public static void main(String[] args) {
        Pattern p = Pattern.compile("(a)(b)(c)");
        String str = "111abc222abc333";
        String out = null;
        Matcher m = p.matcher(str);
        out = m.replaceAll("z$3y$2x$1");
        System.out.println(out);
    }
}

这给出了111zcybxa222zcybxa333 作为输出。
我想你会看到这个例子的作用。

但是好的,我认为没有现成的内置
你可以说的方法例如:
- 将第 3 组替换为 zzz
- 将第 2 组替换为 yyy
- 将第 1 组替换为 xxx

【讨论】:

  • 在这种情况下使用 lambdas 不是很好吗?然后,您可以通过一个小循环运行这些 lambda,甚至可以利用哈希映射将正则表达式组存储为键,并将它们的替换模式存储为值!快点 JDK 8!
  • 更换前无需致电find()。如果没有匹配,replaceAll() 只返回原始字符串。
  • @AlanMoore 同意。已更新。
【解决方案3】:

您可以使用Matcher#start(group)Matcher#end(group) 来构建通用替换方法:

public static String replaceGroup(String regex, String source, int groupToReplace, String replacement) {
    return replaceGroup(regex, source, groupToReplace, 1, replacement);
}

public static String replaceGroup(String regex, String source, int groupToReplace, int groupOccurrence, String replacement) {
    Matcher m = Pattern.compile(regex).matcher(source);
    for (int i = 0; i < groupOccurrence; i++)
        if (!m.find()) return source; // pattern not met, may also throw an exception here
    return new StringBuilder(source).replace(m.start(groupToReplace), m.end(groupToReplace), replacement).toString();
}

public static void main(String[] args) {
    // replace with "%" what was matched by group 1 
    // input: aaa123ccc
    // output: %123ccc
    System.out.println(replaceGroup("([a-z]+)([0-9]+)([a-z]+)", "aaa123ccc", 1, "%"));

    // replace with "!!!" what was matched the 4th time by the group 2
    // input: a1b2c3d4e5
    // output: a1b2c3d!!!e5
    System.out.println(replaceGroup("([a-z])(\\d)", "a1b2c3d4e5", 2, 4, "!!!"));
}

检查online demo here

【讨论】:

  • 这比它需要的复杂得多。见gtgaxiola's answer
  • @AlanMoore appendReplacement() 是一个优雅的解决方案,适用于简单替换就足够的情况。尽管如此,对于那种情况,我认为我的解决方案并不复杂。然而,replaceGroup() 方法解决了一个比简单替换更复杂的问题——并且以一种通用的、参数化的方式。尝试在我的样本main() 上与另一个实现结果,你就会明白我的意思。
  • 我想我可能也找到了另一种解决方案。我想看看 switch 语句是否能以某种方式帮助我们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-25
  • 2012-08-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多