kamaci kamaci - 1 month ago 15
Java Question

Java String ReplaceAll and ReplaceFirst Fails at $ Symbol at Replacement Text

I wrote this 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);
}


This is what happens when I run it:

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


I'm reading data from a file. Should I escape all
$
symbols in the file data, or is this an unnecessary process? Is there any other class or library to handle this situation?

What is the problem with having a special symbol in the replacement text (not in the regex)?

Notes:


  • I don't want to check every character to escape. That's why I am asking this question.

  • I'm using Java 6.


Answer Source

String.replaceAll takes a regular expression matching pattern as its first parameter, and a regular expression replacement pattern as its second parameter - and $ has a specific meaning in regular expressions (in both matching patterns and replacement patterns, although in different senses).

Just use String.replace instead, and I suspect all your problems will go away. You should only use replaceAll when you genuinely want to match/replace via a regular expression - which I don't think you do in this case.

EDIT: As to your question:

What is the problem with having a special symbol in the replacement text (not in the regex)?

Again, the documentation for replaceAll makes this clear:

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; see Matcher.replaceAll. Use Matcher.quoteReplacement(java.lang.String) to suppress the special meaning of these characters, if desired.

So if you want to treat the matching pattern as a regular expression, but not the replacement, then use Matcher.quoteReplacement.