1. 程式人生 > >String.replaceAll替換目標為反斜槓

String.replaceAll替換目標為反斜槓

今天想把string的某些內容替換為File.separator,windows環境出現個小問題,之前沒注意過,記錄下。

問題現象:

public static void main(String[] args) {
		System.out.println("abcad".replaceAll("a", File.separator));
	}
很簡單的程式碼,但執行異常:

JDK1.6

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 1
	at java.lang.String.charAt(String.java:686)
	at java.util.regex.Matcher.appendReplacement(Matcher.java:703)
	at java.util.regex.Matcher.replaceAll(Matcher.java:813)
	at java.lang.String.replaceAll(String.java:2189)
	at com.aires.login.LoginUtil.main(LoginUtil.java:12)

JDK1.8也拋異常,但異常資訊有調整:
Exception in thread "main" java.lang.IllegalArgumentException: character to be escaped is missing
	at java.util.regex.Matcher.appendReplacement(Matcher.java:809)
	at java.util.regex.Matcher.replaceAll(Matcher.java:955)
	at java.lang.String.replaceAll(String.java:2223)
	at com.aires.login.LoginUtil.main(LoginUtil.java:12)

查看了下原始碼,String.replaceAll是通過Matcher.appendReplacement實現,在該實現中,如果遇到轉義字元,則取下一個字元作為替換字元,而windows下的File.separator恰好為轉義字元\,所以導致問題出現。
char nextChar = replacement.charAt(cursor);
            if (nextChar == '\\') {
                cursor++;//此處如果發現是轉義字元\,將向後移動一位
                nextChar = replacement.charAt(cursor);
                result.append(nextChar);
                cursor++;
            }


正確需要如下形式:

public static void main(String[] args) {
		System.out.println("abcad".replaceAll("a", "\\\\"));
	}

另外$也是一個特殊字元(用於獲取分組),使用時需要轉義

"abcad".replaceAll("a", "\\$")