yoplay one
yoplay one

Reputation: 31

Java matcher how to dynamically replace groups based on their value

For a quick sample, I have the following string:

String s = "hey.there.man.${a.a}crazy$carl${a.b}jones

I also have the following method:

private String resolveMatchedValue(String s) {
    if(s.equals("a.a")) {
           return "A";
    else if(s.equals("a.b")) { 
           return "Wallet";
    else if(.....
    ....
 }

My pattern would be

 Pattern pattern = Pattern.compile("\\$\\{(.*?)\\}");

So for every substring in s that matches ${.*} I want there to be a call to the resolveMatchedValue method and it should be replaced with that. So ideally after the regex process s should be

 s = "hey.there.man.Acrazy$carl$Walletjones

I've looked at similar solutions but nothing that dynamically replaces the matched values based on the matched value, and have not been able to get it to work

edit: using java8

Upvotes: 2

Views: 2436

Answers (1)

sprinter
sprinter

Reputation: 27966

In order to capture just the right characters you should exclude right curly brace from your group [^}]+. In fact it's better practice to just include the specific pattern you are looking for to catch errors early:

Pattern pattern = Pattern.compile("\\$\\{([a-z]\\.[a-z]+)\\}");

The method Matcher.replaceAll​(Function<MatchResult,String> replacer) is designed to do exactly what you are asking for. The function passed to the method is given each match and returns a string to replace it with.

In your case:

pattern.matcher(input).replaceAll(mr -> resolveMatchedValue(mr.group(1)));

Will return a string with all substrings matching your pattern replaced.

Here's a working example that just uppercases the fields:

System.out.println(Pattern.compile("\\$\\{([[a-z]\\.[a-z])\\}")
    .matcher("hey.there.man.${a.a}crazy$carl${a.b}jones")
    .replaceAll(mr -> mr.group(1).toUpperCase()));

Prior to Java 9 an equivalent is:

StringBuffer result = new StringBuffer();
while (matcher.find()) {
    matcher.appendReplacement(result, resolvedMatchedValue(matcher.group(1)));
}
matcher.appendTail(result);

After which result.toString() holds the new string.

Upvotes: 10

Related Questions