欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java SE: String.replaceAll() with special character "$"

程序员文章站 2022-04-28 21:59:47
...

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);
    }
}
    2) If we cannot predefine (hardcode) the replacement(the replacement is passed in as parameter):
    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