How to appendReplacement on a Matcher group instead of the whole pattern?

cottonBallPaws picture cottonBallPaws · Oct 15, 2010 · Viewed 15.1k times · Source

I am using a while(matcher.find()) to loop through all of the matches of a Pattern. For each instance or match of that pattern it finds, I want to replace matcher.group(3) with some new text. This text will be different for each one so I am using matcher.appendReplacement() to rebuild the original string with the new changes as it goes through. However, appendReplacement() replaces the entire Pattern instead of just the group.

How can I do this but only modify the third group of the match rather than the entire Pattern?

Here is some example code:

Pattern pattern = Pattern.compile("THE (REGEX) (EXPRESSION) (WITH MULTIPLE) GROUPS");
Matcher matcher = pattern.matcher("THE TEXT TO SEARCH AND MODIFY");
StringBuffer buffer = new StringBuffer();

while(matcher.find()){
   matcher.appendReplacement(buffer, processTheGroup(matcher.group(3));
}

but I would like to do something like this (obviously this doesn't work).

...
while(matcher.find()){
   matcher.group(3).appendReplacement(buffer, processTheGroup(matcher.group(3));
}

Something like that, where it only replaces a certain group, not the whole Pattern.

EDIT: changed the regex example to show that not all of the pattern is grouped.

Answer

Warren picture Warren · Mar 24, 2011

I see this already has an accepted answer, but it is not fully correct. The correct answer appears to be something like this:

.appendReplacement("$1" + process(m.group(2)) + "$3");

This also illustrates that "$" is a special character in .appendReplacement. Therefore you must take care in your "process()" function to replace all "$" with "\$". Matcher.quoteReplacement(replacementString) will do this for you (thanks @Med)

The previous accepted answer will fail if either groups 1 or 3 happen to contain a "$". You'll end up with "java.lang.IllegalArgumentException: Illegal group reference"