Java Regex and the Dollar Sign

I came across an interesting problem today that got 3 hrs wasted for no good reason. In my application, I have templates and I replace variables with values that are read from a file. And I use the plain old String.replaceAll to do the job. So it happened this afternoon that I landed upon the following error:

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:2189)

As informative as it is, I did a bit of debugging and read a few articles only to realise that it was a dollar sign ($) in one of the values that was causing the issue. Now the deal is that Java regex uses the $ sign as a group separator and so it does not like that to appear in the text. Suggestions on the net include escaping the $ with back slashes but no matter how many slashes I put, it did not work.  So I wrote a simple little hack:


static String escapeForRegex(String text) {

if (text.contains("$")) {

StringBuffer sb = new StringBuffer();

for (char c : text.toCharArray()) {

if (c == '$') {

sb.append("__DOLLAR_SIGN__");

} else {

sb.append(c);

}

}

text = sb.toString();

}

return text;

}

And when you are done with all replacements on the string, just do a


text.replaceAll("__DOLLAR_SIGN__", "\\$")

I know, its a hack. Unfortunately I haven’t found a better way out yet. Posting so that if somebody needs it in desperate times, he does not have to spend 3 hrs on it.

Advertisements

6 Comments

  1. Thanks for the tip. It helps me save some time 🙂

    Anyway, I think I have found the true reason (after some hours). Java 6 replaceAll should be used for regex, but in this case, we just need to replace string: a simple “replace” function is enough.

    At here, it is said that
    String.replace() “replaces each substring of this string that matches the literal target sequence with the specified literal replacement sequence.” So in this case, we should use replace() not replaceAll()

    Reply

  2. The $ symbol allows you to back reference matched groups in your regular expression. That is why you get this exception, although I agree the exception is not very clear.

    You don’t have to implement this ugly method to workaround this problem, simply use the Matcher.quoteReplacement() method instead. If you don’t need regexp I suggest you use the simpler “replace()” method.

    Christophe.

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s