This weblog is officially about inane things I run into while trying to do my job at work. Let’s say you have a String object like this:
String mystring = "Your password: #PASSWORD";
and at runtime you need to replace the value of #PASSWORD
with a password that a user typed in. You’d write something like this:
String password = "$Jslwe"
mystring = mystring.replaceAll("#PASSWORD", password);
What would happen? You’d expect that the key #PASSWORD
would get replaced with the value of the variable ‘password’ (which is “$Jslwe”) and then you’d move happily on your way to something much more interesting. But no, Java throws you an error:
java.lang.IllegalArgumentException: Illegal group reference
which is extremely helpful. Turns out that the second argument to the String replaceAll method “may” have some issues with dollar signs and backslashes which you only find out about if you dig into the Matcher class that backs the replaceAll method or if you’re lucky and you read about the whole thing on a site devoted to regular expressions. In short:
myString.replaceAll(“regex”, “replacement”) replaces all regex matches inside the string with the replacement string you specified. No surprises here. All parts of the string that match the regex are replaced. You can use the contents of capturing parentheses in the replacement text via $1, $2, $3, etc. $0 (dollar zero) inserts the entire regex match. $12 is replaced with the 12th backreference if it exists, or with the 1st backreference followed by the literal “2” if there are less than 12 backreferences. If there are 12 or more backreferences, it is not possible to insert the first backreference immediately followed by the literal “2” in the replacement text.
In the replacement text, a dollar sign not followed by a digit causes an IllegalArgumentException to be thrown. If there are less than 9 backreferences, a dollar sign followed by a digit greater than the number of backreferences throws an IndexOutOfBoundsException. So be careful if the replacement string is a user-specified string. To insert a dollar sign as literal text, use \$ in the replacement text. When coding the replacement text as a literal string in your source code, remember that the backslash itself must be escaped too: “\\$”.
Hmmmm, I like MessageFormat more for the problem as stated.
Yepp. MessageFormat is the better choice here.
Thanks a lot! Your short explanation probably saved me a couple of hours reading javadocs.
I’d use StringKit’s ‘format’ method, as in the following example:
String mystring = “Your password: ?”;
Integer userCode = new Integer(5);
String password = “$Jslwe”
String newString = StringKit.format(mystring, userCode);
// newString is “Your password: 5”
String newString = StringKit.format(mystring, password);
// newString is “Your password: $Jslwe”
—
Map map = new HashMap();
map.put(“code”, new Integer(67));
map.put(“pw”, “$t*#@!$\”R12”);
String mystring = “Your password: ${pw}; code: ${code}”;
String newString = StringKit.format(mystring, map);
// newString is “Your password: $t*#@!$”R12; code: 67”
—
I just haven’t had the time to set up a site for StringKit, but I can provide you the source code if you want.
Regards,
Elifarley
elifarley a t Gmail d.o.t.com
// problem resolved by
// Matcher.quoteReplacement(password)
String mystring = “Your password: #PASSWORD”;
String password = “$Jslwe”;
password = Matcher.quoteReplacement(password);
mystring = mystring.replaceAll(“#PASSWORD”, password);
when we are trying to view the attachment file this error is occuring java.land.IllegalArgumentException:{stream type is mandatory} what is the cause of this error why it is occuring
ajohnson /Victor
You are a life saver.
A great big thank you…You have saved me about 3 hours of mind-numbing pain… I am grateful..no I am in your debt..!
Thanks a lot! This was exactly what I needed to fix my proggy.
Greets from Germany!
Hi,
This saved my hours of efforts
Great work done
Thanks a million.
password = Matcher.quoteReplacement(password);
Many thanks to ajonson and Victor.
best regards!
Many thanks. If I hadn’t found your post I probably would have been stuck on this for hours.
Thanks a lot Mr. Victor
I have been trying out for a solution and i got it from your reply.
Saved me a lot of time.
// problem resolved by
// Matcher.quoteReplacement(password)
Thank you Victor. That saved me hours!
Thanks a lot ! Hours saved
This could have taken me hours to work out. Thanks Victor!
Thanks Aaron and Victor. Good catch!
THanks a lot Victor.
You are the man! Thank you so much!
It’s interesting how something so little as using a $ sign in a password can cause so much havoc. I had been debugging a Data Warehouse client (DAC) application for 3 days. It was failing at the beginning of a preETL phase with a cryptic error of:
com.siebel.etl.engine.bore.NewDispatcher.run(Unknown Source)
java.lang.Thread.run(Thread.java:534)
19 SEVERE Tue Nov 18 15:26:14 CST 2008 MESSAGE:::Illegal group reference
EXCEPTION CLASS::: java.lang.IllegalArgumentException
java.util.regex.Matcher.appendReplacement(Matcher.java:561)
java.util.regex.Matcher.replaceAll(Matcher.java:661)
java.lang.String.replaceAll(String.java:1663)
com.siebel.etl.engine.core.AttachToInformaticaProcess.getCommand(Unknown Source)
After looking at your posting, I noticed the $$ at the end of the informatica server admin password that was saved in the DAC to communicate with informatica.
You saved my arse with your posting… THANK YOU SO MUCH!
You rock. Saved me heaps of time!
Great. Thanks a lot.
My problem was exactly the dollar sign. I solved it by replacing dollar signs:
replace = replace.replaceAll(“\\$”,”\\\\\\$”);
(provided by a reader at http://www.bennadel.com/blog/255-Issues-with-Dollar-Signs-And-Java-s-Matcher-AppendReplacement-Method.htm)
I failed my exam because I didn’t know this. 🙁
Next time…
Its useful… How can i change (YEAR/MM/DATE) format to (DD/MMM/YEAR)???
You have no idea how much time you saved!!
Thank you so much!!
Really appreciate you thought to share this with us.
Thanks a lot Victor.
In a live system, I got this error and searched in google, found your article, and solved in a few minutes.
Thank you.
Thanks lot victor.you save my time.
Many thanks to ajonson and Victor.
best regards!
Thank you!
Great work victor, its saved lots of my effort
Post is still helping! Brilliant!
thanks allot!
I was getting this error with Maven Replacer Plugin. I was looking for “(…)” since it said there was an error with my capture groups. You put me on the right track to realize the replacement of “${scmBranch}” (from the Maven BuildNumber Plugin) was being interpreted as a capture group due to the “$”. “\${scmBranch}” did the trick.
Thanks!
freakin’ brilliant! i had no idea what was causing pig to throw an ” ERROR 2999: Unexpected internal error. Illegal group reference”.
i typically use the group function in pig, so was wondering what in the heck was going on.
avoiding the $ in a pig parameter substitution seems like the best solution for me, and it completely solved my issue.
i can’t believe this issue isn’t better documented or even fixed, since your original post was MORE THAN 5 YEARS AGO! holy cow.
thanks for that post – the gift that keeps on giving!
Thanks victor.. that was a great help
Thanks Victor Matcher.quoteReplacement(password). This saved my time
Testers found this bug in our new deploy. Thanks Victor for the quote replacement method.
I couldn’t get a SQL script to open because of this error message. Turns out you can’t have a $ in the name of your script. Thanks for mentioning the $ issue in the beginning of your blog. I only lost 5 minutes on this issue until I came here. Thanks again!
Thanks Victor..