Replace group 1 of Java regex with out replacing the entire regex

Aditya :

I have a regex pattern that will have only one group. I need to find texts in the input strings that follows the pattern and replace ONLY the match group 1. For example I have the regex pattern and the string to be applied on as shown below. The replacement string is "<---->"

Pattern p = Pattern.compile("\\w*(lan)\\w+");
Matcher m = p.matcher("plan plans lander planitia");

The expected result is

plan p<--->s <--->der p<--->itia

I tried following approaches

    String test = "plan plans lander planitia";
    Pattern p = Pattern.compile("\\w*(lan)\\w+");
    Matcher m = p.matcher(test);
    String result = "";
    while(m.find()){
        result = test.replaceAll(m.group(1),"<--->");
    }
    System.out.print(result);

This gives result as

p<---> p<--->s <--->der p<--->itia

Another approach

    String test = "plan plans lander planitia";
    Pattern p = Pattern.compile("\\w*(lan)\\w+");
    Matcher m = p.matcher(test);
    String result = "";
    while(m.find()){
        result = test.replaceAll("\\w*(lan)\\w+","<--->");
    }
    System.out.print(result);

Result is

plan <---> <---> <--->

I have gone through this link. Here the part of the string before the match is always constant and is "foo" but in my case it varies. Also I have looked at this and this but I am unable to apply any on the solutions given to my present scenario.

Any help is appreciated

Wiktor Stribiżew :

You need to use the following pattern with capturing groups:

(\w*)lan(\w+)
^-1-^   ^-2-^

and replace with $1<--->$2

See the regex demo

The point is that we use a capturing group around the parts that we want to keep and just match what we want to discard.

Java demo:

String str = "plan plans lander planitia";
System.out.println(str.replaceAll("(\\w*)lan(\\w+)", "$1<--->$2"));
// => plan p<--->s <--->der p<--->itia

If you need to be able to replace the Group 1 and keep the rest, you may use the replace callback method emulation with Matcher#appendReplacement:

String text = "plan plans lander planitia";
String pattern = "\\w*(lan)\\w+";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(text);
StringBuffer sb = new StringBuffer();
while (m.find()) {
    m.appendReplacement(sb, m.group(0).replaceFirst(Pattern.quote(m.group(1)), "<--->"));
}
m.appendTail(sb); // append the rest of the contents
System.out.println(sb.toString());
// output => plan p<--->s <--->der p<--->itia

See another Java demo

Here, since we process a match by match, we should only replace the Group 1 contents once with replaceFirst, and since we replace the substring as a literal, we should Pattern.quote it.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=455448&siteId=1