断言

断言是对当前匹配点前后字符的测试,它实际上不消耗任何字符。 编码为 \b、\B、\A、\Z、\z、^ 和 $ 的简单断言在 转义序列 中进行了描述。 更加复杂的断言被编码为子模式。 有两种类型:向前看当前位置在主题字符串中的位置,以及向后看它的位置。

断言子模式以正常方式匹配,只是它不会导致当前匹配位置发生变化。 向前看断言以 (?= 开头(用于肯定断言),以 (?! 开头(用于否定断言)。 例如,\w+(?=;) 匹配一个后面跟着分号的单词,但不包括分号在匹配中,而 foo(?!bar) 匹配任何不以 "bar" 结尾的 "foo" 出现。 请注意,类似的模式 (?!foo)bar 不会找到以 "foo" 以外的任何内容结尾的 "bar" 出现;它会找到任何 "bar" 出现,因为当接下来的三个字符是 "bar" 时,断言 (?!foo) 始终为 true。 需要使用向后看断言来实现此效果。

向后看断言以 (?<= 开头(用于肯定断言),以 (?<! 开头(用于否定断言)。 例如,(?<!foo)bar 会找到不以 "foo" 结尾的 "bar" 出现。 向后看断言的内容受到限制,以便它匹配的所有字符串都必须具有固定长度。 但是,如果有多个备选方案,它们并不都必须具有相同的固定长度。 因此,(?<=bullock|donkey) 是允许的,但 (?<!dogs?|cats?) 会在编译时导致错误。 只有在向后看断言的顶层,才能允许匹配不同长度字符串的分支。 这比 Perl 5.005 进行了扩展,Perl 5.005 要求所有分支匹配相同长度的字符串。 例如,(?<=ab(c|de)) 这样的断言是不允许的,因为它单个顶层分支可以匹配两种不同的长度,但如果重写为使用两个顶层分支,则它是可以接受的:(?<=abc|abde)。 向后看断言的实现是,对每个备选方案,临时将当前位置向后移动固定宽度,然后尝试匹配。 如果当前位置之前没有足够的字符,则匹配被视为失败。 向后看与一次性子模式结合使用,对于在字符串结尾处匹配特别有用;在一次性子模式部分的结尾给出了一个示例。

可以在多个断言(任何类型)中连续出现。 例如,(?<=\d{3})(?<!999)foo 匹配以三个不是 "999" 的数字结尾的 "foo"。 请注意,每个断言都在主题字符串中的同一点被独立应用。 首先,检查前三个字符是否都是数字,然后检查相同的三个字符是否不是 "999"。 此模式不匹配以六个字符结尾的 "foo",其中第一个是数字,最后三个不是 "999"。 例如,它不匹配 "123abcfoo"。 执行此操作的模式是 (?<=\d{3}...)(?<!999)foo

这次,第一个断言查看前六个字符,检查前三个是否为数字,然后第二个断言检查前三个字符是否不是 "999"。

断言可以以任何组合嵌套。 例如,(?<=(?<!foo)bar)baz 匹配以 "bar" 结尾的 "baz" 出现,而 "bar" 又不以 "foo" 结尾,而 (?<=\d{3}...(?<!999))foo 是另一种模式,它匹配以三个数字和三个不是 "999" 的任何字符结尾的 "foo"。

断言子模式不是捕获子模式,并且不能重复,因为重复断言同一个东西没有意义。 如果任何类型的断言在其内部包含捕获子模式,则这些子模式将被计入整个模式中捕获子模式的编号目的。 但是,子字符串捕获只对肯定断言进行,因为对否定断言来说没有意义。

断言计入 200 个带括号的子模式的最大值。

添加说明

用户贡献说明

此页面没有用户贡献的说明。
To Top