PCRE正则语法
PHP Manual

断言

一个断言就是一个对当前匹配位置之前或之后的字符的测试, 它不会实际消耗任何字符. 简单的断言代码有\b, \B, \A, \Z, \z, ^, $等等. 更加复杂的断言以子组的方式编码. 它有两种类型: 前瞻断言(从当前位置向前测试)和后瞻断言(从当前位置向后测试)

一个断言子组的匹配还是通过普通方式进行的, 不同在于它不会导致当前的匹配点发生改变. 前瞻断言中的正面断言(断言此匹配为真)以”(?=”开始, 消极断言以”(?!”开头. 比如, \w+(?=;)匹配一个单词紧跟着一个分号但是匹配结果不会包含分号, foo(?!bar)匹配所有后面没有紧跟”bar”的”foo”字符串. 注意一个类似的模式(?!foo)bar, 它不能用于查找之前出现所有不是”foo”的”bar”匹配, 它会查找到任意的”bar”出现的情况, 因为(?!foo)这个断言在接下来三个字符时”bar”的时候是永远都TRUE的. 前瞻断言需要达到的就是这样的效果.

后瞻断言中的正面断言以”(?<=”开始, 消极断言以”(?<!”开始. 比如, (?<!foo)bar用于查找任何前面不是”foo”的”bar”. 后瞻断言的内容被严格限制为只能用于匹配定长字符串. 但是, 如果有多个可选分支, 它们不需要拥有相同的长度. 比如(?<=bullock|donkey)是允许的, 但是(?<!dogs?|cats?)将会引发一个编译期的错误.在最上级分支可以匹配不同长度的字符串是允许的. 相比较于perl 5.005而言, 它会要求多个分支使用相同长度的字符串匹配. (?<=ab(c|de))这样的断言是不允许的, 因为它单个的顶级分支可以匹配两个不同的长度, 但是它可以接受使用两个顶级分支的写法(?<=abc|abde)这样的断言实现, 对于每个可选分支, 暂时将当前位置移动到尝试匹配的当前位置之前的固定宽度处. 如果在当前没有足够的字符就视为匹配失败.后瞻断言与一次性子组结合使用可以用来匹配字符串结尾; 一个例子就是在一次性子组上给出字符串结尾.

多个断言(任意顺序)可以同时出现. 比如(?<=\d{3})(?<!999)foo匹配前面有三个数字但不是”999”的字符串”foo”. 注意, 每个断言独立应用到对目标字符串该点的匹配. 首先它会检查前面的三位都是数字, 然后检查这三位不是”999”. 这个模式不能匹配”foo”前面有三位数字然后紧跟3位非999共6个字符的字符串, 比如, 它不匹配”123abcfoo”. 匹配”123abcfoo”这个字符串的模式可以是(?<=\d{3}…)(?<!999)foo.

这种情况下, 第一个断言查看(当前匹配点)前面的6个字符, 检查前三个是数字, 然后第二个断言检查(当前匹配点)前三个字符不是”999”

断言可以以任意复杂度嵌套. 比如(?<=(?<!foo)bar)baz匹配前面有”bar”但是”bar”前面没有”foo”的”baz”. 另外一个模式(?<=\d{3}…(?<!999))foo则匹配前面有三个数字字符紧跟3个不是999的任意字符的”foo”.

断言子组时非捕获子组, 并且不能用量词修饰, 因为对同一件事做多次断言是没有意义的.如果所有的断言都包含一个捕获子组, 那么为了在整个模式中捕获子组计数的目的, 它们都会被计算在内. 然而, 子字符串的捕获仅可以用于正面断言, 因为对于消极的断言是没有意义的.

将断言计算在内, 可以拥有的最大子组数量是200个.


PCRE正则语法
PHP Manual