3

How, exactly, do you replace groups while appending them to a string buffer? For Example: (a)(b)(c) How can you replace group 1 with d, group 2 with e and so on? I'm working with the Java regex engine. Thanks in advance.

  • 1
    possible duplicate of [Can I replace groups in Java regex?](http://stackoverflow.com/questions/988655/can-i-replace-groups-in-java-regex) – Marcel Stör Jan 07 '14 at 20:52

3 Answers3

6

You could use Matcher's appendReplacement

Here is an example sample using:

input: "hello bob How is your cat?"

regular expression: "(bob|cat)"

output: "hello alice How is your dog"

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 "";
}
Alan Moore
  • 73,866
  • 12
  • 100
  • 156
gtgaxiola
  • 9,241
  • 5
  • 42
  • 64
1

Are you looking for something like this?

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);
    }
}

This gives 111zcybxa222zcybxa333 as output.
I guess you will see what this example does.

But OK, I think there's no ready built-in
method through which you can say e.g.:
- replace group 3 with zzz
- replace group 2 with yyy
- replace group 1 with xxx

peter.petrov
  • 38,363
  • 16
  • 94
  • 159
  • Wouldn't it be nice to have lambdas for this kind of case? Then, you could run those lambdas through a little loop, and even utilize hash maps to store regex groups as keys and their replacement patterns as values! Hurry up JDK 8! – Jesus Kevin Morales Jan 07 '14 at 21:06
  • You don't need to call `find()` before doing the replacement. If there are no matches, `replaceAll()` simply returns the original string. – Alan Moore Jan 07 '14 at 21:46
  • @AlanMoore Agreed. Updated. – peter.petrov Jan 07 '14 at 21:53
1

You could use Matcher#start(group) and Matcher#end(group) to build a generic replacement method:

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, "!!!"));
}

Check online demo here.

acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • That's much more complicated than it needs to be. See [gtgaxiola's answer](http://stackoverflow.com/a/20981946/20938). – Alan Moore Jan 07 '14 at 21:49
  • @AlanMoore `appendReplacement()` is an elegant solution for the cases where a simple replacement would suffice. Even still, for that case, I don't think my solution is complicated. Nevertheless, the method `replaceGroup()` solves a much more elaborated problem than simply replacing -- and in a generic, parameterized, way. Try achieving the results on my sample `main()` with the other and you'll get what I mean. – acdcjunior Jan 07 '14 at 22:06
  • I think I may have found another solution as well. I'm trying to see if switch statements could help us out somehow. – Jesus Kevin Morales Jan 07 '14 at 23:44