The Problem with Regex Search and Replace in Java
2021 July 15

I had an issue where I needed to support search and replace of certain quoted strings in various scripts which take the form of $(VARNAME). There’s a minor issue with Java where if the replaced by string contains certain characters where it will quit with an unhelpful message like “IndexNotFound: Match group 5 not found” or something similar. This is how to resolve that error, and the importance of escaping things.

The method Matcher.appendReplacement is used to search and replace in a specialized fashion with Java regexes for instance we need to take some action based on what the exact match was. The example shown on the javadoc is as follows:

Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat two cats in the yard");
StringBuffer sb = new StringBuffer();
while (m.find()) {
    m.appendReplacement(sb, "dog");
}
m.appendTail(sb);
System.out.println(sb.toString());

The above will replace all instances of “cat” with “dog”. However what if the need is to replace “cat” by something with special characters like “$”. You’ll get an exception like so:

Exception in thread "main" java.lang.IllegalArgumentException: Illegal group reference: group index is missing
	at java.util.regex.Matcher.appendReplacement(Matcher.java:819)
	at T.main(T.java:9)

This is all explained in the javadoc per the quote below:

Note that backslashes () and dollar signs ($) in the replacement string may cause the results to be different than if it were being treated as a literal replacement string. Dollar signs may be treated as references to captured subsequences as described above, and backslashes are used to escape literal characters in the replacement string.

Luckily java provides a wonderful method called, Matcher.quoteReplacement that handles the quoting for the replacement, and the output is exactly as expected when the string replaced string uses that.

*****
Written by Henry J Schmale on 2021 July 15