正则表达式笔记 7 零宽断言(预先搜索,预匹配)

Regex :

  • 本文介绍正则表达式中断言(Assertion)的用法
  • 本文的正则表达式用 Java 7 测试
  • 本文的正则表达式用         高亮标出


State :

四种断言:

格式英文说明 (From Java 7 Doc)中文说明
(?=X)X, via zero-width positive look ahead零宽度正预测先行断言
(?!X)X, via zero-width negative look ahead零宽度负预测先行断言
(?<=X)X, via zero-width positive look behind零宽度正预测后发断言
(?<!X)X, via zero-width positive look behind零宽度负预测后发断言

Note :

  1. 以上四种断言是零宽度匹配的,而不像 [a-z] 一样能匹配一个字符
  2. [From StackOverflow: Java doesn't support variable length in look behind.对于后发断言在Java中与逆向引用一起使用的问题
  3. 请见下面详解:


How 2 use ? :

  • (?=X) 表达的含义是向前搜索,寻找符合表达式 X 的字符串,其实是预匹配,而不真正匹配
    • 如我需要寻找前缀是 "hand" 的单词,那么可以这样写 \b(?=hand)\w+\b
       1: String source = "Please put up your hand! Hey, handsome boy, I mean you." +
       2:         "Don't forget to handle your problem.";    
       3: Pattern pattern = Pattern.compile("\\b(?=hand)\\w+\\b");
       4: Matcher matcher = pattern.matcher(source);
       5: while (matcher.find()) {
       6:     System.out.println(matcher.group());
       7: }
       1: //Output:
       2: hand
       3: handsome
       4: handle
     
  • (?!X) 也是向前搜索,! 表示“非”,所以搜索到的内容不符合 X 的定义才算预匹配成功

 

  • (?<=X) 表达的含义是向后搜索,预匹配表达式 X
    • 同上,如果我们需要寻找后缀为 "er" 的单词,那么可以这样写 \b\w+(?<=er)\b
       1: String source = "doctor actor lawyer or a singer\n" +
       2:         "why not president be a dreamer\n" +
       3:         "you can be just the one you wanna be\n" +
       4:         "police man fire fighter or a post man\n" +
       5:         "why not something like your old man\n" +
       6:         "you can be just the one you wanna be";        
       7: Pattern pattern = Pattern.compile("\\b\\w+(?<=er)\\b");
       8: Matcher matcher = pattern.matcher(source);
       9: while (matcher.find()) {
      10:     System.out.println(matcher.group());
      11: }
       1: //output
       2: lawyer
       3: singer
       4: dreamer
       5: fighter

 

  • (?<!X) 也是向后搜索,与上反义

image


Mistakes : 错误用法

  • 我需要匹配这样的字符串:以小写字母开头、数字结束,如 "abc12", "Ggicci1991", "G5"
    • 错误写法:[a-z]+(?<=\d+),从自然语言去描述这个正则表达式好似“小写字母开头,至少一个,后面跟着的是至少一个数字”,而实际上这个表达式什么都不能匹配
    • 错误原因:对零宽度这个概念不理解,(?<=\d+)并不会单独去匹配字符,也就是说
         1: System.out.println(Pattern.matches("[a-z](?<=b)", "ab")); --> false
         2: System.out.println(Pattern.matches("[a-z](?<=b)", "a")); --> false
         3: System.out.println(Pattern.matches("[a-z](?<=b)", "f")); --> false
         4: System.out.println(Pattern.matches("[a-z](?<=b)", "b")); –> true
      [a-z](?<=b) 它只能匹配一个字符,即 b。因为它的含义是:匹配一个字符,在a-z的范围内,而且这个字符的后缀为b,显然一个字符后缀为b的只有b啊。
      故 [a-z]+(?<=\d+) 匹配不到任何内容的原因在于不可能存在一段小写字母构成的字符串中还出现数字字符的。
    • 正确写法:[a-z]+\d+


Exception Sample :

Look-behind group does not have an obvious maximum length near index ..

        在 Java 7 里面 \d{4}-[\w&&[^_]]{4}-\d{4}-\d{4,8}(?<=7+) 可以的,在 Regex look-behind without obvious maximum length in Java 上面看到先前的版本貌似对 (?<=7+) 或者 (?<=7*) 中的 + 和 * 不支持,都用一个区域 {min, max} 来解除这个异常。不过在 Java 7 中还是不能在后发断言(look behind)中使用逆向引用(Back reference:Backreferences in lookbehind,或者可以,不过我还不会,谁会的话说一声啊!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值