锁定老帖子 主题:一个诡异的字符串替换BUG
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2014-03-08
最后修改:2014-03-08
将字符串中的数字替换成$D
希望将以下字符串中的数字替换为$D字符 引用 ab1cd2 我们知道String有3个用于字符替换的方法,分别是:
由于我们希望所有替换,因此使用如下方法: 代码1:StringReplaceTest public class StringReplaceTest { @Test public void testReplace(){ String str = "ab1cd2"; System.out.println(str.replaceAll(str, "$D")); } } 小小代码现诡异异常 运行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个匹配分组--终于真相大白了,是我们闯了雷区了 来看一个例子加深一个印象: @Test public void testReplace2(){ String str = "刘备是张飞的小弟"; System.out.println(str.replaceAll("(刘备)是(张飞)", "$2是$1")); //=>张飞是刘备的小弟 } 李鬼出来,李逹进去 李鬼现形,处理起来自然简单: @Test public void testReplace(){ String str = "ab1cd2"; System.out.println(str.replaceAll(str, "\\$D")); //=>ab$Dcd$D } 小评一下 如果JDK可以再分析一下$,将$N即N是数字时才对其进行特殊处理,否则就不当成特殊字符,是不是更好一些呢? 也许这样并不好,必须这样造成Matcher方法为了这个小概率事件做很多复杂的检查,结果是得不偿失的。还是遇到特殊字符报异常,让开发者去处理更好些,这是28原来取舍得当的一个API设计。既然$是特殊字符,开发者绕过即可。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2014-03-12
请问意义何在
|
|
返回顶楼 | |
发表时间:2014-03-13
rex0654335 写道 请问意义何在
+1 |
|
返回顶楼 | |
发表时间:2014-03-14
rex0654335 写道 请问意义何在
+2 楼下跟上 |
|
返回顶楼 | |
发表时间:2014-03-14
挺好的。看来API要仔细看啊
|
|
返回顶楼 | |
发表时间:2014-03-14
rex0654335 写道 请问意义何在
+1 |
|
返回顶楼 | |
发表时间:2014-03-14
最后修改:2014-03-14
意义何在是指啥呢?当然方法要放在具体上下文中才有意义,我故意将上下文去掉了,重点突出这个API容易出错的情况,所以无需关注我这段代码有什么具体意义啊。
|
|
返回顶楼 | |
发表时间:2014-03-14
public static void main(String args[]){
String str = "ab1cd2"; System.out.println(str.replaceAll("\\d", Matcher.quoteReplacement("$D"))); } |
|
返回顶楼 | |
发表时间:2014-03-14
goldenfish1919 写道 public static void main(String args[]){ String str = "ab1cd2"; System.out.println(str.replaceAll("\\d", Matcher.quoteReplacement("$D"))); } +1 |
|
返回顶楼 | |
发表时间:2014-03-25
$符合本身就是正则表达式里面的特殊符合,string自带的方法替换本身就支持正则表达式。不挂才怪
|
|
返回顶楼 | |