25

我最近在阅读PCRE- (Perl-compatible regular expressions) 文档,并遇到了一些关于正则表达式的有趣技巧。当我继续阅读并精疲力尽时,我因为与使用一些(*...)模式有关的一些困惑而停下来。

我的问题和困惑(*PRUNE)(*FAIL)

现在作为参考(*SKIP)(*PRUNE)除了如果模式未锚定,bumpalong 前进不是到下一个字符,而是到遇到的主题中的位置。(*SKIP)

文档指出,如果模式的其余部分不匹配,(*PRUNE)则会导致匹配在主题的当前起始位置失败。它与否定断言(*FAIL)同义。在模式中的给定位置(?!)强制匹配失败。

所以基本上(*FAIL)表现得像一个失败的否定断言,是的同义词(?!)

如果后面的匹配失败导致回溯到达它,则导致匹配在主题(*PRUNE)的当前起始位置失败。

当涉及到失败点时,这些有何不同?

任何人都可以提供如何正确实施和使用这些示例吗?

4

1 回答 1

37

在阅读此答案之前,您应该熟悉回溯机制、原子组和所有格量词。您可以在 Friedl 书中找到有关这些概念和功能的信息,并点击以下链接:www.regular-expressions.infowww.rexegg.com

所有测试都是通过全局搜索(使用preg_match_all()函数)进行的。

(*FAIL) (或简写(*F)

baabo caaco daado

caac(*FAIL)|aa.|caaco|co

[0] => aab
[1] => caaco
[2] => aad

(*FAIL)导致与模式中的“坏字符”完全相同的行为。例如,如果您将其替换为“R”,您将获得完全相同的结果:caacR|aa.|caaco|co. 更笼统地说,您确实可以(*FAIL)用“总是失败的子模式”代替:(?!), (?=a(?<!a)),...

a (first from "baabo"): 不出所料,第一个结果是由第二种选择找到的。( aab)

c (first):正则表达式引擎遇到第一个“c”并尝试第一个替代方案并找到:caac,但子模式被迫失败。然后正则表达式引擎(总是从第一个“c”开始)尝试第二个失败的替代方案,第三个替代方案成功。( caaco)

a (first from "daado"): 第三个结果是由第二种选择找到的。( aad)

(*SKIP)

baabo caaco daado

caa(*SKIP)c(*FAIL)|aa.|caaco|co

[0] => aab
[1] => co
[2] => aad

这个动词定义了一个点,当子模式稍后失败时,正则表达式引擎不允许回溯。因此,之前使用子模式找到的所有字符都被一次性使用,并且不能用于模式的另一部分(替代方案)。

a (first from "baabo"): 第一个结果是由第二个备选方案找到的。( aab)

c (first):正则表达式引擎caac在第一种情况下找到,然后失败((*FAIL)动词的原因),回溯到第二个“c”,但不允许回溯到(*SKIP)动词之前先前匹配的字符(“caa”)。
c (second):现在,正则表达式引擎总是尝试第一个替代方案,但在这个新位置并失败,因为后面有一个“o”而不是“a”,然后它回溯到第二个“c”。请注意,在这种情况下,这些字符不会像以前那样被消耗,因为子模式之前未能到达(*SKIP)动词。第二种选择经过测试并失败(不以“c”开头)。第三种选择也失败了,因为下一个字符是“o”而不是“a”。第四种选择成功并给出了第二个结果。co( )

a (first from "daado"): 第三个结果是由第二种选择找到的。( aad)

(*PRUNE)

baabo caaco daado

caa(*PRUNE)c(*FAIL)|aa.|caaco|co

[0] => aab
[1] => aac
[2] => aad

这个动词不同,(*SKIP)因为它不禁止使用所有先前匹配的字符,但如果子模式稍后将失败,则跳过子模式的第一个匹配字符(或禁止子模式开始)。

a (first from "baabo"): 第一个结果是由第二个备选方案找到的。( aab)

c (first):正则表达式引擎caac在第一种情况下找到,然后失败,但现在从“caaco”回溯到第一个“a”,因为第一个“c”被跳过。
a (first from "caaco"): 第一个选项被尝试并失败,第二个成功并给出第二个结果。( aac)

a (first from "daado"): 第三个结果是由第二种选择找到的。( aad)

于 2013-11-15T19:12:24.417 回答