• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

String replaceAll problem with $

 
Bruce Jin
Ranch Hand
Posts: 672
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

String x = "aaa XXX bbb";
String replace = "XXX";
String y = "xy$z";
x = x.replaceFirst(replace, y);

Here y is a variable which may contain $.

$ in y caused error:
java.lang.IllegalArgumentException: Illegal group reference

How to handle $ here?

Thanks!
 
Maneesh Godbole
Saloon Keeper
Posts: 11196
15
Android Eclipse IDE Google Web Toolkit Java Mac Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Bruce Jin:

Here y is a variable which may contain $.

$ in y caused error:
java.lang.IllegalArgumentException: Illegal group reference

How to handle $ here?

Thanks!


$ is treated as the end of line boundry matcher.
Take a look at the API for Pattern class. The replaceFirst(..) uses pattern matching internally. To quote from the replaceFirst(...) API
Replaces the first substring of this string that matches the given regular expression with the given replacement.
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24212
35
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
... which means you have to use the "escape character" to tell the regular expression compiler to ignore the "$". You have to use a backslash, but since in a Java String a backslash is special, too, you have to use two backslashes to get a literal backslash into the String:

String y = "xy\\$z";
 
Bruce Jin
Ranch Hand
Posts: 672
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks.

How to escape a variable that may contain $?

y.replaceAll("\\$", "\\$");

would not work.

Thanks!
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[Maneesh]: $ is treated as the end of line boundry matcher.

Not here, it isn't. When calling replaceFirst() or replaceAll(), the first argument is a regular expression, which follows the rules of java regular expressions as described in java.util.regex.Pattern. But the second argument is not a regex; it's a replacement text - which has different rules. Quoting from the String.replaceFirst() API: "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.replaceFirst(java.lang.String). Use Matcher.quoteReplacement(java.lang.String) to suppress the special meaning of these characters, if desired."

If you follow the link to Matcher.replaceFirst() it refers you to Matcher.appendReplacement() which has more detail: "The replacement string may contain references to subsequences captured during the previous match: Each occurrence of $g will be replaced by the result of evaluating group(g). The first number after the $ is always treated as part of the group reference. Subsequent numbers are incorporated into g if they would form a legal group reference. Only the numerals '0' through '9' are considered as potential components of the group reference. If the second group matched the string "foo", for example, then passing the replacement string "$2bar" would cause "foobar" to be appended to the string buffer. A dollar sign ($) may be included as a literal in the replacement string by preceding it with a backslash (\$)."

In other words, $1 would be capture group 1, $6 would be capture group 6. $z doesn't make sense to the matcher - that's what "Illegal group reference" means here. Because z is not a group.

And to fix this problem, you can either do as EFJ showed, putting a double backslash in front of the $, or you can use Matcher.quoteReplacement() as suggested in the replaceFirst() API:

[ September 24, 2007: Message edited by: Jim Yingst ]
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[Bruce]: y.replaceAll("\\$", "\\$");

would not work.


In what way did it not work? What did you expect to happen, and what did happen? Offhand your example looks like it should do nothing at all.
 
Bruce Jin
Ranch Hand
Posts: 672
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks.

I am limited to JDK 1.4 so I can not use Matcher.quoteReplacement() witch is only in Jdk 1.5.

Since y is a variable I tried to escape it at runtime by using

y = y.replaceAll("\\$", "\\$");

But still y = "ab$xy" after this. $ is not escaped.

One way to handle this might be

y = y.replaceAll("\\$", "somejunk");

Then do other replace

Then do:

x = x.replaceAll("somejunk", "\$");

Thanks!
 
Kevin Baun
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Bruce Jin:
Thanks.

How to escape a variable that may contain $?

y.replaceAll("\\$", "\\$");

would not work.

Thanks!


you 'do' realize that if you run the snippit as you have it here you are just replacing all the "$" with more "$".... right? Is there some other problem? have you tried to match against the hex value of the $ character?
 
Alan Moore
Ranch Hand
Posts: 262
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
 
Bruce Jin
Ranch Hand
Posts: 672
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Alan.

That makes '$' '\$'!
 
amaan khanpro
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
String x="abc$$abc";
String y=x.replaceAll("\\$\\$", "Amaan");
System.out.println(y);
 
Campbell Ritchie
Sheriff
Pie
Posts: 50278
80
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic