I was working on an internal project that is used for archiving user’s blog posts. I released this application to an internal community and it was recieved quite well by the users. I made sure that the code was bug free, as far as I tested it and the code was working as expected with out any serious issues. But what is an application when there is no bug in it?
One user got back to me saying that the code successfully downloaded the blog posts but it failed during the index building process. The index building process was doing a simple string replacement, replacing a pattern with the list of archived posts links. I was using String.replaceAll() method for this. The user reported back that he is getting the exception: java.lang.IllegalArgumentException: Illegal group reference.
Initially I was clueless about why it is throwing the exception. But later when I debugged the code, I found that the exception was thrown because of the $ symbols that were present in the parameters to the replaceAll() method. To make it clear, have a look at the below code:
public static void main(String args[]) throws Exception {
String template = "The user has spent amount in a day";
String pattern = "amount";
String output = template.replaceAll(pattern, "$ 100");
System.out.println(output);
}
If you think that the above code will run without a issue and print “The use has spent $ 100 in a day”, then you are wrong. Here’s what this code will spit out:
Exception in thread "main" java.lang.IllegalArgumentException: Illegal group reference
at java.util.regex.Matcher.appendReplacement(Matcher.java:713)
at java.util.regex.Matcher.replaceAll(Matcher.java:813)
at java.lang.String.replaceAll(String.java:2190)
at demo.BugDemo.main(BugDemo.java:16)
Java Result: 1
The exception is thrown because the replacement string (i.e. “$ 100″) contains a $ symbol in it. And the Matcher.appendReplacement() class internally uses the $ symbol as a identifier for grouping. So inorder to avoid this, the $ symbol in the replacement string needs to be escaped using \$. So after this fix, the correct code for the above program would be:
String output = template.replaceAll(pattern, "\$ 100");
Hm.. perfect. This incident reminds me that debugging can teach us a lot than the actual development.



{ 11 comments… read them below or add one }
Good one. I believe String class should say the same docs as it was in Matcher.replaceAll() which is added in string.replaceAll()….
agreed. Otherwise it is little difficult to figure it out why the replaceAll() method fails.
Yes, debugging teaches a few lessons.
I thought it was due to $ being a regex symbol. Pardon me, I am not a Java programmer, but know javascripting.
java.util.regex namespace gave me solace
Did you try with other regex symbols like ^
I haven’t tested the code for other regex symbols, but I guess those symbols also should be escaped.
Veera, the replaceAll method takes in regular expressions as the parameter and ‘$’ in regex is a special character that represents end of a line.
Grouping, on the other hand is done using parantheses.
according to the API documentation of Matcher.appendReplacement method,
and that’s what I meant by grouping.
thx you saved a lot of my time
dudes,
String oldPattern = Pattern.quote( aOldPattern );
String newPattern = Matcher.quoteReplacement( aNewPattern );
return aInput.replaceAll( oldPattern, newPattern );
that should word.
Thank you very much Veera, that solved my problem. A huge string that may take a whole day to find the error. I just removed $ and its working, wow, what a fail:P
A good post!
// This incident reminds me that debugging can teach us a lot than the actual development.//
Well said