day52-正则表达式03( 二 )


文章插图
5.7反向引用

请看下面的问题:
给定一段文本 , 请找出所有四个数字连在一起的子串 , 并且这四个数字要满足:
  1. 第一位与第四位相同
  2. 第二位与第三位相同
在解决前面的问题之前 , 我们需要了解正则表达式的几个概念:
  1. 分组
    我们可以用圆括号组成一个比较复杂的匹配模式 , 那么一个圆括号的部分我们可以看作是一个子表达式/分组
  2. 捕获
    把正则表达式中的 子表达式/分组 匹配的内容 , 保存到内存中以数字编号或显式命名的组里 , 方便后面引用 , 从左向右 , 以分组的左括号为标志 , 第一个出现的分组的组号为1 , 第二个为2 , 以此类推 。组0代表的是整个正则式
    -详见5.4.6
  3. 反向引用
    圆括号的内容被捕获后 , 可以在这个括号后被使用 , 从而写出一个比较实用的匹配模式 , 这个我们称为反向引用 , 这种引用既可以是在正则表达式内部 , 也可以是在正则表达式外部 , 内部反向引用使用\\分组号 , 外部反向引用使用$分组号
5.7.1反向引用的匹配原理捕获组(Expression)在匹配成功时 , 会将子表达式匹配到的内容 , 保存到内存中一个以数字编号的组里 , 可以简单的认为是对一个局部变量进行了赋值 , 这时就可以通过反向引用方式 , 引用这个局部变量的值 。一个捕获组(Expression)在匹配成功之前 , 它的内容可以是不确定的 , 一旦匹配成功 , 它的内容就确定了 , 反向引用的内容也就是确定的了 。
反向引用必然要与捕获组一同使用的 , 如果没有捕获组 , 而使用了反向引用的语法 , 不同语言的处理方式不一致 , 有的语言会抛异常 , 有的语言会当作普通的转义处理 。
  • 看几个小案例
    1. 要匹配两个连续的相同数字(\\d)\\1
    2. 要匹配五个连续的相同数字(\\d)\\1{4}
    3. 要匹配个位与千位相同 , 十位与百位相同的数(\\d) (\\d)\\2\\1
    4. 在字符串中检索商品编号 , 形式如:12321-333999111这样的号码 , 要求满足前面是一个五位数 , 然后一个-号 , 然后是一个九位数 , 连续的每三位要相同
例子:
package li.regexp;import java.util.regex.Matcher;import java.util.regex.Pattern;//反向引用public class RegExp12 {public static void main(String[] args) {String content = "ke7887k5225e he12341551l12321-333999111lo ja11ck yy22y xx33333x";//1. 要匹配两个连续的相同数字(\\d)\\1//String regStr="(\\d)\\1";//2. 要匹配五个连续的相同数字(\\d)\\1{4}//String regStr="(\\d)\\1{4}";//3. 要匹配个位与千位相同 , 十位与百位相同的数(\\d)(\\d)\\2\\1//String regStr="(\\d)(\\d)\\2\\1";//在字符串中检索商品编号 , 形式如:12321-333999111这样的号码 , // 要求满足前面是一个五位数 , 然后一个-号 , 然后是一个九位数 , 连续的每三位要相同String regStr="\\d{5}-(\\d)\\1{2}(\\d)\\2{2}(\\d)\\3{2}";Pattern pattern = Pattern.compile(regStr);Matcher matcher = pattern.matcher(content);while (matcher.find()){System.out.println("找到:"+matcher.group(0));}}}5.7.2去重
经典的结巴程序
把类似“我.....我我要......学学学学.......编程java!”

经验总结扩展阅读