1. Problem Description:
When replacement contains "$", either IllegalArgumentException or StringIndexOutOfBoundsException will be thrown.
The reason is that replaceAll() is not simply character replacement, it uses regex as "placeholder expression".
And the character "$" is treated as the end of line boundry matcher in regex.
Java API for replaceAll() method:
public String replaceAll(String regex, String replacement);
JavaDoc For replaceAll() method:
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 java.util.regex.Matcher.quoteReplacement to suppress the special meaning of these characters, if desired.
Case 1:
package edu.xmu.string;
public class ReplaceAllTest {
public static void main(String[] args) {
String str = "abcdefg";
String placeholder = "abc";
String replacement = "a$bc";
String replacedStr = str.replaceAll(placeholder, replacement);
System.out.println(replacedStr);
}
}
Exception in thread "main" java.lang.IllegalArgumentException: Illegal group reference
at java.util.regex.Matcher.appendReplacement(Matcher.java:808)
at java.util.regex.Matcher.replaceAll(Matcher.java:906)
at java.lang.String.replaceAll(String.java:2162)
at edu.xmu.string.ReplaceAllTest.main(ReplaceAllTest.java:8)
Case 2:
package edu.xmu.string;
public class ReplaceAllTest {
public static void main(String[] args) {
String str = "abcdefg";
String placeholder = "abc";
String replacement = "abc$";
String replacedStr = str.replaceAll(placeholder, replacement);
System.out.println(replacedStr);
}
}
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 4
at java.lang.String.charAt(String.java:658)
at java.util.regex.Matcher.appendReplacement(Matcher.java:772)
at java.util.regex.Matcher.replaceAll(Matcher.java:906)
at java.lang.String.replaceAll(String.java:2162)
at edu.xmu.string.ReplaceAllTest.main(ReplaceAllTest.java:8)
2) Available Solutions:
1) If we may predefine (hardcode) the replacement:
package edu.xmu.string;
public class ReplaceAllTest {
public static void main(String[] args) {
String str = "abcdefg";
String placeholder = "abc";
String replacement = "\\$abc"; // Use backslash to make sure "$" is treated as normal character
String replacedStr = str.replaceAll(placeholder, replacement);
System.out.println(replacedStr);
}
}
Manually preprocess for special character in replacement.
package edu.xmu.string;
public class ReplaceAllTest {
public static void main(String[] args) {
String str = "abcdefg";
String placeholder = "abc";
String replacement = "$abc";
replacement = replacement.replaceAll("\\$", "\\\\\\$"); // preprocessment for the special character in replacement.
String replacedStr = str.replaceAll(placeholder, replacement);
System.out.println(replacedStr);
}
}
Or automatically preprocess for special character in replacement.
package edu.xmu.string;
import java.util.regex.Matcher;
public class ReplaceAllTest {
public static void main(String[] args) {
String str = "abcdefg";
String placeholder = "abc";
String replacement = "$abc";
replacement = Matcher.quoteReplacement(replacement); // preprocessment for the special character in replacement.
String replacedStr = str.replaceAll(placeholder, replacement);
System.out.println(replacedStr);
}
}
Or use Apache's StringUtils.replace(...), it is preferred if all we need is simple character replacement without using regex.
package edu.xmu.string;
import org.apache.commons.lang.StringUtils;
public class ReplaceAllTest {
public static void main(String[] args) {
String str = "abcdefg";
String placeholder = "abc";
String replacement = "$abc";
String replacedStr = StringUtils.replace(str, placeholder, replacement); // apache's StringUtils do not use regex for replacement.
System.out.println(replacedStr);
}
}
Reference Links:
1) http://www.coderanch.com/t/383666/java/java/String-replaceAll