我们知道String replaceAll(参数a, 参数b) 参数a是需要些正则表达式的. 但是今天试了试,发现参数b也有一些其它特性.
查看源码后,发现有些特性是平时不怎么用的.下面我来介绍一下这两个参数的特性.

参数a是正则表达式这个就没什么特色了.
参数b有点特殊.
参数b中对\ 和 $ 进行了特殊处理.
查看源码可以发现最后会调用下面的方法:
java.util.regex.Matcher的appendReplacement方法
下面对参数a和参数b一些特殊用法进行详细的介绍,并带有实例:
特性1:参数b里会对\进行特殊处理.
  1. 类似于正则的用法. \\\\四个反斜线,最后会表示为一个\反斜线.
  2. String s = "a(bc)d_abcd";
  3. System.out.println(s.replaceAll("_", "\\\\_"));
  4. 结果:
  5. a(bc)d\_abcd


特性2:参数b中如果出现$后面跟着数字,相当于对前面的正则表达式的反向引用.(类似于正则中的\1这种效果)
分组号为0-9之间的数字.
  1. String testg = "amfooniceshow";
  2. //$2 相当于对前面正则表达式的第二组进行引用
  3. System.out.println(testg.replaceAll("(am)(foo)", "$2haha"));
  4. 结果:
  5. foohahaniceshow


特色3:参数a语法:(<?name>) 参数b语法:${name}源码中还对这种格式进行特殊处理.
刚开始我试了几种写法,发现会报错,如下.
Exception in thread "main" java.lang.IllegalArgumentException: No group with name {xxx}
at java.util.regex.Matcher.appendReplacement(Matcher.java:800)
at java.util.regex.Matcher.replaceAll(Matcher.java:906)
at java.lang.String.replaceAll(String.java:2162)
看了源码中的注释也没对这种用法做特殊说明.在网上搜了一下发现国内外所有的网站都没有说明${name}用法
而我却偏偏想知道这是怎么用的,我接车自己查看源码,发现在参数a中需要写特殊语法才能操作.

在java.util.regex.Pattern中的group0()方法中有这段操作,会对namedGroups进行操作.
 在java.util.regex.Matcher的appendReplacement方法,会对namedGroups进行判断.
如果参数a没有按照<?name>格式写参数的话,后面的判断就会报错.
 
参数a中的这种写法(<?name>)这种格式基本没人用,国内外网上一片文章都没有.
java的正则文档对这种写法也是只字未提.
经过看源码和测试发现
参数a中:(<?name>)  然后在参数b中${name}对前面的进行引用.
(<?name>)这种相当于零宽度匹配(和非捕获组区别在于,这个是有分组的),name必须是大小写字母,不能是其它的,是其它的就会编译不通过.
参数b是${name} 是对前面的进行引用.可以引用也可以不引用(效果一样,下面有示例验证).
简单示例:
  1. String test1 = "hahaamfooniceshowerqwhdfgsd";
  2. System.out.println(test1.replaceAll("(?<sho>)wer", "${sho}123456"));
  3. 结果:
  4. hahaamfoonicesho123456qwhdfgsd


验证它存在分组的示例:
  1. //结果是1, 相当于有一个组,这种是()被认为是一个分组.
  2. Pattern p = Pattern.compile("(?<xxx>)");
  3. System.out.println(p.matcher("ab").groupCount());
  4. //常规的结果是0, 相当于没有新建分组
  5. Pattern pp = Pattern.compile("xxx");
  6. System.out.println(pp.matcher("ab").groupCount());
  7. //常规的非捕获组结果也是0, 相当于没有新建分组
  8. Pattern ppp = Pattern.compile("(?<=xxx)");
  9. System.out.println(ppp.matcher("ab").groupCount());

下面两段
  1. package com.xjl456852.manager;
  2. import java.util.regex.Matcher;
  3. /**
  4. * Created by xjl456852 on 2017/3/9.
  5. */
  6. public class StringTest {
  7. public static void main(String args[]) {
  8. String s = "a(bc)d_abcd";
  9. System.out.println(s.replaceAll("_", "\\\\_"));
  10. //会出错
  11. // System.out.println(s.replaceAll("_", "\\\\$"));
  12. System.out.println(s.replaceAll("_", "\\\\\\$"));
  13. //可用Matcher.quoteReplacement() 对replaceAll的第二个参数进行转义
  14. System.out.println(s.replaceAll("_", Matcher.quoteReplacement("\\$")));
  15. System.out.println(s.replaceAll("_", "\\$"));
  16. System.out.println(s.replaceAll("_", "\\."));
  17. System.out.println(s.replaceAll("_", "."));
  18. System.out.println(s.replaceAll("_", "\\\\%"));
  19. System.out.println(s.replaceAll("_", "\\5"));
  20. System.out.println(s.replaceAll("_", "5"));
  21. System.out.println(s.replaceAll("_", "5"));
  22. System.out.println(s.replaceAll("_", "\""));
  23. System.out.println(s.replaceAll("_", "\\\""));
  24. System.out.println(s.replaceAll("_", "\\${1}"));
  25. //会出错 ${} 这个大括号里面不能是数字
  26. // System.out.println(s.replaceAll("_", "${1}"));
  27. String testg = "amfooniceshow";
  28. //$2 相当于对前面正则表达式的第二组进行引用
  29. System.out.println(testg.replaceAll("(am)(foo)", "$2haha"));
  30. System.out.println("--------------");
  31. String test = "hahaam${foo}niceshow";
  32. System.out.println(test.replaceAll("\\$\\{.*\\}", "\\\\\\$\\{ss\\}"));
  33. System.out.println(test.replaceAll("\\$\\{.*\\}", Matcher.quoteReplacement("\\${ss}")));
  34. //会出现错误
  35. // System.out.println(test1.replaceAll("\\$\\{.*\\}", "${ss}"));
  36. }
  37. }
结果:
  1. a(bc)d\_abcd
  2. a(bc)d\$abcd
  3. a(bc)d\$abcd
  4. a(bc)d$abcd
  5. a(bc)d.abcd
  6. a(bc)d.abcd
  7. a(bc)d\%abcd
  8. a(bc)d5abcd
  9. a(bc)d5abcd
  10. a(bc)d5abcd
  11. a(bc)d"abcd
  12. a(bc)d"abcd
  13. a(bc)d${1}abcd
  14. foohahaniceshow
  15. --------------
  16. hahaam\${ss}niceshow
  17. hahaam\${ss}niceshow

另一段程序:
这段程序主要是对${name} 这种特殊用法做了介绍.

  1. package com.xjl456852.manager;
  2. import java.util.regex.Pattern;
  3. /**
  4. * Created by xjl456852 on 2017/3/9.
  5. */
  6. public class StringTest {
  7. public static void main(String args[]) {
  8. System.out.println("下面是${name}格式的replaceAll替换");
  9. String test1 = "hahaamfooniceshowerqwhdfgsd";
  10. System.out.println("--------------------");
  11. //${name} 属于有名字的领宽度匹配的引用.name必须是大写或小写字母,不能是其它符号或者数字.这种用法真是少见,感觉没什么实际的意义.
  12. //${name} 中的name,是一种分组的名字,也就是说在前面的正则中需要写入这样的名字.而且这个名字的写法比较特殊.
  13. //我查看源码之后了解到这种写法必须是<?name>的格式.
  14. //例如下面.它的意思是:sho为零宽度匹配,这个可以匹配wer
  15. System.out.println(test1.replaceAll("(?<sho>)wer", "${sho}123456"));
  16. //下面这两个虽然按理说不能匹配wer,因为<sh>中少了个o,但其实可以匹配wer(这种用法真是不知道在那种场景中才能用到),所以将wer替换为123456
  17. System.out.println(test1.replaceAll("(?<sh>)wer", "123456"));
  18. System.out.println(test1.replaceAll("(?<sh>)wer", "${sh}123456"));
  19. //这个参数b中使用了$1,而(?<sh>)会被认为是一个分组,但是这个又是零宽度的,所以$1相当于没有引用.而$1已经被使用,所以1不会打印出来,只会打印23456
  20. System.out.println(test1.replaceAll("(?<sh>)wer", "$123456"));
  21. System.out.println("----------------------");
  22. //下面这两个写的<xxx>这种字符是不存在的,但是后面的we也会被替换
  23. System.out.println(test1.replaceAll("(?<xxx>)we", "123${xxx}456"));
  24. //下面这个和上面那个一样,<xxx>这个是不存在的,但是ho和we都会被替换掉
  25. System.out.println(test1.replaceAll("ho(?<xxx>)we", "123${xxx}456"));
  26. //这个h后面少了o,后面紧接着是we,故无法匹配字符串,所以会以原字符串输出
  27. System.out.println(test1.replaceAll("h(?<xxx>)we", "123${xxx}456"));
  28. System.out.println("------------------");
  29. //这个也匹配不到,所以无法替换,所以会以原字符串输出
  30. System.out.println(test1.replaceAll("(?<sho>)dwer", "123456"));
  31. //下面这两个都是领宽度匹配,前后都没条件,无论<>中写的是什么字符串,前后都没有条件,就不会匹配任何字符串,按领宽度匹配处理,所以会在每个字符串的前后都插入123.
  32. System.out.println(test1.replaceAll("(?<sho>)", "123"));
  33. System.out.println(test1.replaceAll("(?<xxx>)", "123"));
  34. System.out.println("=============================");
  35. //这个是用非捕获组进行的匹配.会在sh后面插入123
  36. System.out.println(test1.replaceAll("(?<=sh)", "123"));
  37. //其实用非捕获字也能实现这种每个字符的前后都插入相同目标字符串的功能.但是这个有一个特点就是原字符串中必须不包含xxx
  38. System.out.println(test1.replaceAll("(?<!xxx)", "123"));
  39. //比如下面的这个,原字符串中就包含sh,使用?<!sh ,意思是不是sh的字符串都插入123.这时结果跟上一个字符串相比就少了一组123.
  40. // 因为检查到字符s时,发现不是sh,所以会插入123,再次检查到h时,发现是sh,所以不插入,这时会跳过.h后面就会少一组123
  41. System.out.println(test1.replaceAll("(?<!sh)", "123"));
  42. System.out.println("-------------");
  43. //下面是一些其它的写法可以根据结果自己理解.
  44. System.out.println(test1.replaceAll("(?<ha>)haam.*?(ce)(?<sh>).*?(fg)", "12${ha}34${sh}56"));
  45. System.out.println(test1.replaceAll("(?<ha>)haam", "123456${ha}"));
  46. System.out.println(test1.replaceAll("(ce)(?<sh>)", "1234${sh}56"));
  47. System.out.println(test1.replaceAll("ce(?<sh>)", "123456"));
  48. System.out.println("-------------");
  49. System.out.println(test1.replaceAll("(?<sh>)ow", "1234${sh}56"));
  50. System.out.println(test1.replaceAll("(?<sh>)ow", "123456"));
  51. System.out.println("-------------");
  52. System.out.println(test1.replaceAll("(ce)(?<sh>)(ow)", "1234${sh}56"));
  53. System.out.println(test1.replaceAll("ce(?<sh>)ow", "1234${sh}56"));
  54. System.out.println(test1.replaceAll("(?<sh>)", "1234${sh}56"));
  55. System.out.println(test1.replaceAll("(?<haam>)", "123${haam}456"));
  56. System.out.println("---------------------");
  57. System.out.println(test1.replaceAll("(?<xxx>)", "123${xxx}456"));
  58. System.out.println(test1.replaceAll("(?<xxx>)", "123456"));
  59. //结果是1, 相当于有一个组,这种是()被认为是一个分组.
  60. Pattern p = Pattern.compile("(?<xxx>)");
  61. System.out.println(p.matcher("ab").groupCount());
  62. //常规的结果是0, 相当于没有新建分组
  63. Pattern pp = Pattern.compile("xxx");
  64. System.out.println(pp.matcher("ab").groupCount());
  65. //常规的非捕获组结果也是0, 相当于没有新建分组
  66. Pattern ppp = Pattern.compile("(?<=xxx)");
  67. System.out.println(ppp.matcher("ab").groupCount());
  68. }
  69. }

  1. 下面是${name}格式的replaceAll替换
  2. --------------------
  3. hahaamfoonicesho123456qwhdfgsd
  4. hahaamfoonicesho123456qwhdfgsd
  5. hahaamfoonicesho123456qwhdfgsd
  6. hahaamfoonicesho23456qwhdfgsd
  7. ----------------------
  8. hahaamfoonicesho123456rqwhdfgsd
  9. hahaamfoonices123456rqwhdfgsd
  10. hahaamfooniceshowerqwhdfgsd
  11. ------------------
  12. hahaamfooniceshowerqwhdfgsd
  13. 123h123a123h123a123a123m123f123o123o123n123i123c123e123s123h123o123w123e123r123q123w123h123d123f123g123s123d123
  14. 123h123a123h123a123a123m123f123o123o123n123i123c123e123s123h123o123w123e123r123q123w123h123d123f123g123s123d123
  15. =============================
  16. hahaamfoonicesh123owerqwhdfgsd
  17. 123h123a123h123a123a123m123f123o123o123n123i123c123e123s123h123o123w123e123r123q123w123h123d123f123g123s123d123
  18. 123h123a123h123a123a123m123f123o123o123n123i123c123e123s123ho123w123e123r123q123w123h123d123f123g123s123d123
  19. -------------
  20. ha123456sd
  21. ha123456fooniceshowerqwhdfgsd
  22. hahaamfooni123456showerqwhdfgsd
  23. hahaamfooni123456showerqwhdfgsd
  24. -------------
  25. hahaamfoonicesh123456erqwhdfgsd
  26. hahaamfoonicesh123456erqwhdfgsd
  27. -------------
  28. hahaamfooniceshowerqwhdfgsd
  29. hahaamfooniceshowerqwhdfgsd
  30. 123456h123456a123456h123456a123456a123456m123456f123456o123456o123456n123456i123456c123456e123456s123456h123456o123456w123456e123456r123456q123456w123456h123456d123456f123456g123456s123456d123456
  31. 123456h123456a123456h123456a123456a123456m123456f123456o123456o123456n123456i123456c123456e123456s123456h123456o123456w123456e123456r123456q123456w123456h123456d123456f123456g123456s123456d123456
  32. ---------------------
  33. 123456h123456a123456h123456a123456a123456m123456f123456o123456o123456n123456i123456c123456e123456s123456h123456o123456w123456e123456r123456q123456w123456h123456d123456f123456g123456s123456d123456
  34. 123456h123456a123456h123456a123456a123456m123456f123456o123456o123456n123456i123456c123456e123456s123456h123456o123456w123456e123456r123456q123456w123456h123456d123456f123456g123456s123456d123456
  35. 1
  36. 0
  37. 0

String replaceAll 正则注意事项及特殊用法(xjl456852原创)的更多相关文章

  1. JAVA中string.replace()和string.replaceAll()的区别及用法

    乍一看,字面上理解好像replace只替换第一个出现的字符(受javascript的影响),replaceall替换所有的字符,其实大不然,只是替换的用途不一样.    public String r ...

  2. [转]String.Replace 和 String.ReplaceAll 的区别

    JAVA 中的 replace replaceAll 问题: 测试code System.out.println("1234567890abcdef -----> "+&qu ...

  3. Java String.replaceAll() 与后向引用(backreference)

    问题 昨天看到一篇博文,文中谈到一道 Java 面试题: 给定一字符串,若该字符串中间包含 "*",则删除该 "*":若该字符串首字符或尾字符为 "* ...

  4. Java用代码演示String类中的以下方法的用法

    用代码演示String类中的以下方法的用法 (1)boolean isEmpty(): 判断字符串是不是空串,如果是空的就返回true (2)char charAt(int index): 返回索引上 ...

  5. Java String.replaceAll()方法

    声明  以下是java.lang.String.replaceAll()方法的声明 public String replaceAll(String regex, String replacement) ...

  6. String replaceAll(String regex,String str)满足正则表达式的部分替换为给定内容

    package seday02;/*** * String replaceAll(String regex,String str)* @author xingsir*/public class Rep ...

  7. (转)正则表达式:string.replaceAll()中的特殊字符($ \)与matcher.appendReplacement

    string.replaceAll中的特殊字符 string.replaceAll(String regex, String replacement)中的replacement参数即替换内容中含有特殊 ...

  8. 1.用代码演示String类中的以下方法的用法 (2018.08.09作业)

    public class Test_001 { public static void main(String[] args) { String a = "德玛西亚!"; Strin ...

  9. String formate的语法解析及简单用法

    转自:https://blog.csdn.net/jiangyu1013/article/details/52607257 package cn.wuxiangbin.StringFormat; im ...

随机推荐

  1. 杂项-Java:FreeMarker

    ylbtech-杂项-Java:FreeMarker 1.返回顶部 1. FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页.电子邮件.配置文件.源 ...

  2. UEditor动态添加图片访问路径前缀

    在使用UEditor上传图片时发现上传图片后在编辑器中不能显示上传的图片,在这里是需要在jsp/config.json中设置图片访问路径前缀,即项目的根路径,在config.json只能填写字符串的配 ...

  3. 0623-TP框架整理一(下载、入口文件、路由、创建控制器、调用模板、系统常量、命名空间)

    一.下载解压后用ThinkPHP(核心)文件 核心文件夹(ThinkPHP)不要改,是作用于全局的,有需要可以改应用目录(Application) 二.创建入口文件: 运行后出现欢迎界面,在说明系统自 ...

  4. 引水入城 2010年NOIP全国联赛提高组(bfs+贪心)

    1066 引水入城 2010年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond     题目描述 Description 在一个遥远 ...

  5. [Swift通天遁地]一、超级工具-(7)创建一个图文并茂的笔记本程序

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  6. jQuery多项选择器

    jQuery多项选择器模式: $("selector1,selector2,selectorN"); 将每一个选择器匹配到的元素合并后一起返回,可以指定任意多个选择器,并将匹配到的 ...

  7. 【计蒜客习题】 取石子游戏(gcd)

    问题描述 蒜头君和花椰妹在玩一个游戏,他们在地上将 n 颗石子排成一排,编号为 1 到 n.开始时,蒜头君随机取出了 2 颗石子扔掉,假设蒜头君取出的 2 颗石子的编号为 a, b.游戏规则如下,蒜头 ...

  8. 对路径 obj 文件夹访问被拒绝

    TFS 刚下载的项目,出现该问题. 解决方案: 将文件夹属性“只读”,取消

  9. Vue知识点小总结1

    ES6常用语法 变量的定义 let定义变量 不会变量提升 有全局作用域和函数作用域,块级作用域{} 不能重复定义 var定义变量 会变量提升 只有全局作用域和函数作用域 能够重复定义 const定义变 ...

  10. 51nod1459 迷宫游戏

    1459 迷宫游戏 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 你来到一个迷宫前.该迷宫由若干个房间组成,每个房间都有一个得分,第一次进入这个房间,你 ...