String字符串替換的一個詭異問題

將字符串中的數字替換成$D 

但願將如下字符串中的數字替換爲$D字符 
java

引用正則表達式


   ab1cd2 
app



咱們知道String有3個用於字符替換的方法,分別是: 
spa

  • String replace(CharSequence target, CharSequence replacement):將字符串中出現的target替換成replacement;.net

  • String replaceAll(String regex, String replacement):regex是一個正則表達式,將字符串中匹配的子字符串替換爲replacement;設計

  • String replaceFirst(String regex, String replacement):和replaceAll(..)相似,只不過只替換第一個出現的地方。orm



因爲咱們但願全部替換,所以使用以下方法: 
代碼1:StringReplaceTest 
事件

Java代碼 開發

  1. public class StringReplaceTest {  字符串

  2.     @Test   

  3.     public void testReplace(){  

  4.         String str = "ab1cd2";  

  5.         System.out.println(str.replaceAll(str, "$D"));  

  6.     }  

  7. }  



小小代碼現詭異異常 

運行StringReplaceTest,控制檯卻沒有返回正確的結果,而是拋出以下的異常: 

引用


java.lang.IllegalArgumentException: Illegal group reference 
at java.util.regex.Matcher.appendReplacement(Matcher.java:713) 
at java.util.regex.Matcher.replaceAll(Matcher.java:813) 
at java.lang.String.replaceAll(String.java:2189) 
at com.hsit.euler.qform.engine.jdbc.StringReplaceTest.testReplace(StringReplaceTest.java:17) 



比較詭異吧,難道是JDK的BUG??? 

剝絲入繭,原來如此 

其實String的replaceAll()及replaceFirst()方法內部都是調用java.util.regex.Matcher的String replaceAll(String replacement)方法的。讓咱們把剛纔的詫異放在一邊,好好看下這個方法的Javadoc,掐頭去尾,主要是這段: 

引用


     * <p> Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in 
     * the replacement string may cause the results to be different than if it 
     * were being treated as a literal replacement string. Dollar signs may be 
     * treated as references to captured subsequences as described above, and 
     * backslashes are used to escape literal characters in the replacement 
     * string. 



原來是咱們的替換目標串中包含了$這個特殊的字符,由於替換串使用這個引用正則表達式匹配的組,$0表明匹配項,$1表明第1個匹配分組,$1表明第2個匹配分組--終於真相大白了,是咱們闖了雷區了 

來看一個例子加深一個印象: 

Java代碼 

  1. @Test   

  2. public void testReplace2(){  

  3.     String str = "劉備是張飛的小弟";  

  4.     System.out.println(str.replaceAll("(劉備)是(張飛)""$2是$1"));  

  5.     //=>張飛是劉備的小弟  

  6. }  



李鬼出來,李逹進去 
李鬼現形,處理起來天然簡單: 

Java代碼 

  1. @Test   

  2. public void testReplace(){  

  3.     String str = "ab1cd2";  

  4.     System.out.println(str.replaceAll(str, "\\$D"));  

  5.     //=>ab$Dcd$D  

  6. }  




小評一下 

若是JDK能夠再分析一下$,將$N即N是數字時纔對其進行特殊處理,不然就不當成特殊字符,是否是更好一些呢? 

也許這樣並很差,必須這樣形成Matcher方法爲了這個小几率事件作不少複雜的檢查,結果是得不償失的。仍是遇到特殊字符報異常,讓開發者去處理更好些,這是28原來取捨得當的一個API設計。既然$是特殊字符,開發者繞過便可。

相關文章
相關標籤/搜索