文档章节

String字符串替换的一个诡异问题

stamen
 stamen
发布于 2015/08/19 11:41
字数 697
阅读 64
收藏 1

将字符串中的数字替换成$D 

希望将以下字符串中的数字替换为$D字符 

引用


   ab1cd2 



我们知道String有3个用于字符替换的方法,分别是: 

  • String replace(CharSequence target, CharSequence replacement):将字符串中出现的target替换成replacement;

  • String replaceAll(String regex, String replacement):regex是一个正则表达式,将字符串中匹配的子字符串替换为replacement;

  • String replaceFirst(String regex, String replacement):和replaceAll(..)类似,只不过只替换第一个出现的地方。



由于我们希望所有替换,因此使用如下方法: 
代码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设计。既然$是特殊字符,开发者绕过即可。


© 著作权归作者所有

stamen

stamen

粉丝 88
博文 28
码字总数 28437
作品 1
厦门
私信 提问
阿拉伯人用阿拉伯数字吗?——记一次用String#format格式化字符串趟到的雷

要生成一个字符串,其中夹杂着一些动态变化的整数,我们一般是用String.format方法来完成,但是,如果用的不恰当,你可能是得不到正确的整数字符串的。 事情从一个线上崩溃说起,从崩溃堆栈来...

ZxLee
2017/09/25
0
0
php json_decode 返回值为null

今天工作中碰到一个很诡异的问题。从memcache中取出的json字符串无法解析。返回值为null。 我在做一个游戏的认证接口,客户端传入一串加密过的token,我解密以后去memcache中获取用户认证数据...

ClownFish
2012/03/22
5K
2
java 正则表达式时好时坏?

我想替换一部分字符串: 想将如下的内容: 替换为: 诡异的是,时好时坏,有时就可以用,有时就不替换成功? 代码如下: 哪位大神知道为啥,JDK 1.7

码上中国博客
2017/06/05
391
7
『实用』过滤字符串中的幽灵字符

背景: 一段明显的字符串,可能潜伏着看不见 的 幽灵字符。 某些字符 比较常见、常用,比如: r n t 但是,有些 幽灵字符(保守估计 >200~1000个),不仅不常见,而且基本没价值。 这些幽灵字...

InkFx
2017/11/17
0
0
诡异的类型转换

一、前言 最近在做应用迁移时候遇到了一个诡异的类型转换问题,感觉比较有意思,就记录下来和大家分享下。 二、问题的产生 原始系统里面有的一个从数据库查询的伪代码如下: image image 由于...

今天你不奋斗明天你就落后
2017/12/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 如果是个帅小伙你愿意和他出去吗

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 小小编辑推荐:《Ghost 》游戏《死亡搁浅》原声 《Ghost 》游戏(《死亡搁浅》原声) - Au/Ra / Alan Walker 手机党少年们想听歌,请使劲儿戳...

小小编辑
今天
156
6
java通过ServerSocket与Socket实现通信

首先说一下ServerSocket与Socket. 1.ServerSocket ServerSocket是用来监听客户端Socket连接的类,如果没有连接会一直处于等待状态. ServetSocket有三个构造方法: (1) ServerSocket(int port);...

Blueeeeeee
今天
6
0
用 Sphinx 搭建博客时,如何自定义插件?

之前有不少同学看过我的个人博客(http://python-online.cn),也根据我写的教程完成了自己个人站点的搭建。 点此:使用 Python 30分钟 教你快速搭建一个博客 为防有的同学不清楚 Sphinx ,这...

王炳明
昨天
5
0
黑客之道-40本书籍助你快速入门黑客技术免费下载

场景 黑客是一个中文词语,皆源自英文hacker,随着灰鸽子的出现,灰鸽子成为了很多假借黑客名义控制他人电脑的黑客技术,于是出现了“骇客”与"黑客"分家。2012年电影频道节目中心出品的电影...

badaoliumang
昨天
16
0
很遗憾,没有一篇文章能讲清楚线程的生命周期!

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本。 简介 大家都知道线程是有生命周期,但是彤哥可以认真负责地告诉你网上几乎没有一篇文章讲得是完全正确的。 ...

彤哥读源码
昨天
19
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部