PHP Conference Japan 2024

断言

断言是对当前匹配点前后字符的测试,它实际上不消耗任何字符。编码为 \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 相比,这是一个扩展,后者要求所有分支匹配相同长度的字符串。诸如 (?<=ab(c|de)) 之类的断言是不允许的,因为它的单个顶层分支可以匹配两个不同的长度,但如果重写为使用两个顶层分支,则它是可以接受的:(?<=abc|abde) 后顾断言的实现是,对于每个备选方案,暂时将当前位置向后移动固定宽度,然后尝试匹配。如果当前位置之前没有足够的字符,则匹配被认为失败。后顾与一次性子模式结合使用对于在字符串末尾匹配特别有用;在一次性子模式部分的末尾给出了一个示例。

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

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

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

断言子模式不是捕获子模式,并且可能不会重复,因为多次断言同一件事没有意义。如果任何类型的断言在其内部包含捕获子模式,则这些子模式将用于对整个模式中捕获子模式进行编号。但是,子字符串捕获仅对肯定断言执行,因为对否定断言没有意义。

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

添加注释

用户贡献的注释

此页面没有用户贡献的注释。
To Top