注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

G G I C C I

 
 
 

日志

 
 

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

2012-09-25 18:47:46|  分类: 正则表达式 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

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,或者可以,不过我还不会,谁会的话说一声啊!


Regex Sina 点击这里Q我 CSDN
Author : Ggicci     本文属于个人学习笔记,如有错误,希望您能指正!转载请注明出处,谢谢 : ) [网易博客]
  评论这张
 
阅读(1360)| 评论(2)
推荐

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017