kamaci
kamaci

Reputation: 75127

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:

Upvotes: 16

Views: 25860

Answers (5)

MBR
MBR

Reputation: 297

Special character $ can be handled is simple way. Check below example

public static void main(String args[]){
        String test ="Other company in $ city ";
        String test2 ="This is test company ";
        try{
            test2= test2.replaceFirst(java.util.regex.Pattern.quote("test"),  Matcher.quoteReplacement(test));
            System.out.println(test2);
            test2= test2.replaceAll(java.util.regex.Pattern.quote("test"),  Matcher.quoteReplacement(test));
            System.out.println(test2);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

Output:

This is Other company in $ city  company 
This is Other company in $ city  company 

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1500145

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.

Upvotes: 32

rajesh kakawat
rajesh kakawat

Reputation: 10896

Try this one

 String template = "The user has spent amount in a day";
 String pattern = "amount";
 String output = template.replaceAll(pattern, "\\$ 100");
 System.out.println(output);

Upvotes: 1

asgoth
asgoth

Reputation: 35829

$ is used a symbol to specify the replacement group. You need to escape it:

String output = template.replaceAll(pattern, "\\$ 100");

Upvotes: 0

Cory Kendall
Cory Kendall

Reputation: 7304

In a replacement string, $ is a special character: it is used to grab matched groups from the pattern you are replacing. You can read more about it here.

To fix this, you can quote the replacement string to remove all special meaning from $ characters:

import java.util.regex.Matcher;
// ...
String output = template.replaceAll(pattern, Matcher.quoteReplacement("$ 100"));

Upvotes: 7

Related Questions