一次性子组 - php 表达式
一次性子组
对于同时有最大值和最小值量词限制的重复项, 在匹配失败后, 紧接着会以另外一个重复次数重新评估是否能使模式匹配。 当模式的作者明确知道执行上没有问题时, 通过改变匹配的行为或者使其更早的匹配失败以阻止这种行为是很有用的。
考虑一个例子,模式 \d+foo 应用到目标行123456bar时:
在匹配了 6 个数字后匹配 ”foo” 时失败,通常的行为时匹配器尝试使 \d+ 只匹配 5 个数字, 只匹配 4 个数字,在最终失败之前依次进行尝试。 一次性子组提供了一种特殊的意义, 当模式的一部分得到匹配后,不再对其进行重新评估, 因此匹配器在第一次匹配 ”foo” 失败后就能立刻失败。语法符号是另外一种特殊的括号, 以 (?> 开始,比如(?>\d+)bar。
这种括号对模式的一部分提供了”锁定”,当它包含一个匹配之后, 会阻止未来模式失败后对它内部的后向回溯。后向回溯在这里失效, 其他工作照常进行。
换一种说法,如果在目标字符串中当前匹配点是锚点, 这种类型的子组匹配的字符串等同于一个独立的模式匹配。
一次性子组不是捕获子组。如上面的例子,简单而言, 就是尽其所能吃掉尽可能多的匹配字符。因此, 尽管 \d+ 和 \d+? 都会调整要匹配的数字的个数以便模式的其他部分匹配, (?>\d+) 却仅能匹配整个数字序列。
这个(语法)结构可以包含任意复杂度的字符, 也可以嵌套。
一次性子组可以和后瞻断言结合使用来指定在目标字符串末尾的有效匹配。 考虑当一个简单的模式比如abcd$应用到一个不匹配的长字符串上。 由于匹配时从左到右处理的, PCRE会从目标中查找每一个 ”a” 然后查看是否紧接着会匹配模式的剩余部分。 如果模式是^.*abcd$, 那么初始的 .* 将首先匹配整个字符串,但是当它失败后(因为紧接着不是 ”a”), 它会回溯所有的匹配,依次吐出最后 1 个字符,倒数第 2 个字符等等。 从右向左查找整个字符串中的 ”a”, 因此,我们不能很好的退出。然而, 如果模式写作^(?>.*)(?\D+)|)*[!?]就会快速得到报错。(译注: 对于这里给出的模式,当目标字符串更长的时候,消耗时间会迅速增加,慎用。)
鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com
图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!