正则环视 php,php正则表达式环视详解

1. 顺序肯定环视(?=exp)

零宽度正预测先行断言,又称顺序肯定环视,断言自身出现位置的后面能匹配表达式exp。

比如,匹配以“ing”结尾的单词前面部分(除了“ing”以外的部分):bw+(?=ingb)

以上表达式查找以下句子时,会匹配“sing”和“danc”:

I'm singing while you're dancing.

2. 逆序肯定环视(?<=exp)

零宽度正回顾后发断言,又称逆序肯定环视,断言自身出现位置的前面能匹配表达式exp。

比如,以re开头的单词的后半部分(除了re以外的部分):(?<=bre)w+b

以上表达式在查找以下句子时匹配“ading”:

reading a book

假如在很长的数字中,每3位间加1个逗号(当然是从右边加起),可以在前面和里面添加逗号的部分:((?<=d)d{3})+b

用以上表达式对“1234567890”进行查找,结果是“,234,567,890”。这里的逗号只是匹配需要添加逗号的位置,还没有实际添加逗号。

下面这个例子同时使用这两种断言,匹配以空白符间隔的数字(再次强调,不包括这些空白符):(?<=s)d+(?=s)

前面提到过反义,用来查找不是某个字符或不在某个字符类里的字符。如果只是想要确保某个字符没有出现,但并不想去匹配它时怎么办?例如,如果想查找这样的单词——出现字母q,但是q后面跟的不是字母u。可以尝试这样:bw*q[^u]w*b

以上表达式匹配包含后面不是字母u的字母q的单词。但是如果多做几次测试就会发现,如果q出现在单词的结尾,例如Iraq、Benq,这个表达式就会出错。这是因为[^u]总要匹配一个字符,如果q是单词的最后一个字符,后面的“[^u]”将会匹配q后面的单词分隔符(可能是空格、句号或其他),后面的“w*b”将会匹配下一个单词,于是以上表达式就能匹配整个Iraq fighting。

逆序肯定环视能解决这样的问题,因为它只匹配一个位置,并不消费任何字符。现在,解决这个问题如下所示:bw*q(?!u)w*b

3. 顺序否定环视(?!exp)

零宽度负预测先行断言,又称顺序否定环视,断言此位置的后面不能匹配表达式“exp”。例如:

1)匹配3位数字,而且这3位数字的后面不能是数字:d{3}(?!d)

2)匹配不包含连续字符串abc的单词:b((?!abc)w)+b

如果匹配的单词是c开头、t结尾,中间有一个字符,但不能是u(也就是说,整个单词不能是cut),直接用“c[^u]t”就可以了,若中间的字符不能是a或u(也就是说,整个单词不能是cat或cut),则表达式改为“c[^au]t”。

如果认真读过关于排除型字符组的章节的读者肯定会知道,这个表达式能匹配的只是cot之类的单词,因为中间的排除型字符组“[^au]”必须匹配一个字符。可是,如果还想匹配chart、conduct和court怎么办?最简单的想法是:去掉排除型字符组的长度限制,改成“c[^au]+t”。

不幸的是,这样行不通,因为这个表达式的意思是:c和t之间由多于一个“除a或u之外的字符”构成,而chart、conduct和court都包含a或u。

我们发现,其实要否定的是“单个出现的a或u”,而不仅仅是“出现的a或u”,所以才出现这样的问题。要解决这个问题,就应当把意思准确表达出来,变成“在结尾的t之前,不允许只出现一个a或u”。想到这一步,就可以用顺序否定环视(?!…)来解决。表示在这个位置向右,不允许出现子表达式能够匹配的文本,把子表达式规定为“[au]tb”(最后的“b”很重要,它出现在t之后,保证t是单词的结尾字母)。有了限制,匹配a和t之间文本的表达式就随意很多,可以用匹配单词字符的简记法“w”表示,于是整个表达式变成:c(?![au]t b)w+t

注意 这里出现的并不是排除型字符组“[^au]”,而是普通的字符组[au],因为顺序否定环视本身已经表示了否定。

进一步思考,整个匹配文本中都不能出现字符串“cat”,要怎么办呢?这个正则表达式应该是:^(?:(?!cat).)+$

即在文本中的任意位置,都不能出现该字符串。

4. 逆序否定环视(?

零宽度负回顾后发断言,又称逆序否定环视,可以用(?

分析以下表达式,匹配不包含属性的简单HTML标签内的内容:(?<=).*(?=1>)

以上表达式最能表现零宽断言的真正用途。((w+)>)指定前缀为:被尖括号括起来的单词(比如可能是“”),然后是“.*”(任意的字符串),最后是一个后缀(?=1>)。注意后缀里的“/”,用到了前面提过的字符转义;“1”则是反向引用,引用的正是捕获的第一组,即前面(w+)匹配的内容,如果前缀实际上是“”,后缀就是“”。整个表达式匹配的是“”和“”之间的内容(再次提醒,不包括前缀和后缀本身)。

总体而言,环视相当于对“所在位置”附加一个条件,难点就在于找到这个“位置”。这一点解决了,环视就没有什么秘密可言了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值