一个断言就是一个对当前匹配位置之前或之后的字符的测试, 它不会实际消耗任何字符. 简单的断言代码有\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个.