从一个正则表达式说开去

3 篇文章 0 订阅
2 篇文章 0 订阅

算起来接触正则也为时不短,看过一点正则表达式的引擎原理,素来以正则高手自诩。昨日偶然间看到一个正则表达式的入门教程,发现里面居然有不少东西没见过,还有几个正则让我困惑不已,说起来真是惭愧。以后在博大精深的正则面前,我只会说:我刚入门。

 

好了,说正事。有如下的需求,有一串正整数,需要以英文格式展示,即右起每3个数按逗号隔开。正则要干的事就是把要加逗号的部分找出来,比如123456789就是456789 ,12345就是345

 

给出一个正则表达式,((?<=/d)/d{3})+/b ,这东西可大有来头,里面用到的 (?<=/d)在正则表达式中叫做零宽断言( Zero-Width Assertions )。那到底什么叫做 零宽断言 呢?

 

在正则表达式中有4种 零宽断言,分别如下:

 

a(?=exp) 前驱 正向断言匹配右边的字符是否为exp,如windows(?=2) 将匹配windows2中的windows,不会匹配windows3 中的windows
a(?!exp)  负向断言 匹配右边的字符是否不为exp ,如windows(?!=2) 将匹配windows3 中的windows ,不会匹配windows2 中的windows
(?<=exp)a 后驱正向断言 匹配左边的字符是否为exp ,如(?=2) windows 将匹配2windows 中的windows ,不会匹配3windows 中的windows
(?<!exp)a  驱负向断言 匹配 边的字符是否不为exp ,如(?!=2) windows 将匹配3windows 中的windows ,不会匹配2windows 中的windows

 

为什么称为零宽断言呢?是因为它仅仅判断特定位置是否满足exp匹配,然后立即丢弃该匹配,只是将匹配结果(true or false) 返回给引擎(这就是断言 ),并不对字符串的推进造成影响。如上面用 windows(?=2) exp 匹配windows2后下一个开始位置是 windows2中的2 ,虽然对2做了匹配,但接下来的匹配 exp 将重新匹配2(这就是零宽 。初看上面的表格,有一个地方可能会让你感到困惑:按照第三列的描述,后驱和前驱应该对调才对。这样定义是因为正在表达式是从字符串左边向右边进行匹配,所以右边称为“前”,左边称为“后”。

 

有了上面的基础,现在我们来对 ((?<=/d)/d{3})+/b做个简单的分析。/b 匹配词的边界,这里放在最后,将匹配右边界。 /d{3}表示连续3个数字,前面加上断言后表示 连续3个数字的 左边还有数字,所以 123456789中的123和12345中的12都将被丢弃 。换成(?<=/d)(/d{3})+/b会更容易理解,具体分析可以由读者自己完成。

 

仔细观察上面的表格,我们发现前驱断言都出现在右边,后驱断言都出现在左边。那是不是一定要这样写才对呢?

 

其实不是的,前驱、后驱都可以放在a的两边,只不过有个细微而且致命的区别。举个例子,比如用(?=2)windows 来匹配windows2,将不会匹配其中的windows。这是因为 (?=2)windows 表示的是从该词( windows  )开始向右进行匹配,所以断言遇到的第一个字符将是windows中的w,直接断言失败。 同理 a(?<=exp)表示 从a的右边开始向左进行匹配,即exp将首先匹配a。所以使用断言的时候要注意位置对结果的影响。

 

好吧,暂时先说到这里,顺便介绍一位正则大牛,人称:..标 哥,常年混迹于一正则q群,几乎有问必答,答必解题,所以大家还有什么疑问,可以在下面回帖,相信伟大的标哥会看到的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值