惰性量词在PCRE中的工作原理如何?

一点背景:我正在实现一个正则表达式匹配引擎(NFA),它应该支持PCRE兼容模式(我的意思是它应该捕获与PCRE具有相同偏移量的子表达式)。

PCRE的testinput1中有一个我不能完全理解的测试。 它测试懒惰的量词。

所以,正则表达式是

/<a[s]+href[s]*=[s]*          # find <a href=
 (["'])?                       # find single or double quote
 (?(1) (.*?)1 | ([^s]+))       # if quote found, match up to next matching
                                 # quote, otherwise match up to next space
/isx

弦是

<a href="abcd xyz pqr" cats

PCRE的比赛是:

<a href="abcd xyz pqr"

显然是使用懒惰的量词。

据我所知,懒惰的量词不应该使用,直到另一个“贪婪”的方式是根本不可能的。 现在这里有一个可能的贪婪匹配:

<a href="abcd

它使用条件子模式的负分支,没有惰性量词。

所以我正在寻找这个PCRE行为的解释或任何细节/建议为什么懒惰量词在这个测试中匹配。 谢谢!

编辑 :我也检查了TRE库的工作原理。 它是POSIX兼容的NFA引擎。 我修改了原来的一些正则表达式以适应TRE的语法:

#include <stdlib.h>
#include <stdio.h>
#include <tre/tre.h>

int main()
{
    regex_t preg;
    const char * regex = "<a[ ]+href[ ]*=[ ]*(?:(')(.*?)'|[^ ]+)";
    const char * string = "<a href='abcd xyz pqr' cats";
    int cflags = REG_EXTENDED;
    int eflags = 0;
    size_t nmatch = 3;
    regmatch_t pmatch[100];

    tre_regcomp(&preg, regex, cflags);
    tre_regexec(&preg, string, nmatch, pmatch, eflags);

    for (int i = 0; i < nmatch; i++) {
        printf("%d: (%d, %d)n", i, pmatch[i].rm_so, pmatch[i].rm_eo - pmatch[i].rm_so);
    }

    return 0;
}

和输出(使用长度而不是结束偏移)是:

0: (0, 22)
1: (8, 1)
2: (9, 12)

所以关于PCRE的回溯特定行为的建议很可能是错误的......


首先,我只是REGEX世界的初学者。 所以,如果这个答案错了​​,或者我误解了这个问题,我很抱歉。

阅读本书定期表达食谱中的这个定义:

(?(1)then | else)是检查第一个捕获组是否已经匹配的条件。 如果有,则正则表达式引擎会尝试匹配。 如果截获组尚未参加比赛尝试,则尝试其他部分。

  • 有了这个主题: <a href="abcd xyz pqr" cats

    第一个捕获组匹配了第一个"字符”,因此,预期的行为是尝试匹配当时的部分,然后第二个捕获组管理匹配字符串abcd xyz pqr(.*?) ,最后是然后部分设法匹配abcd xyz pqr"(.*?)1 。 REGEX可能会取得成功。

    所以,其他的部分与它的量词不是必需的,事实上它不被使用。 这就好像该量词从未存在过。

  • 有了这个主题: <a href="abcd

    第一个捕捉组匹配了"字符”,现在后面的部分设法将字符串abcd(.*?)匹配,但它永远不会匹配最后一个"字符,因为在主题末尾没有这样的字符。 条件失败。

    REGEX引擎并没有停在这里,你已经使用过(["'])?所以,引擎可能会再次尝试,因为"角色是可选的,并且它继续进行,就好像第一个捕获组不匹配一样是回溯)。 因此,现在引擎达到了条件,不匹配第一个捕获组,其他部分尝试,并设法匹配字符串"abcd"由于回溯, "字符没有与第一个捕获组相匹配,现在它由其他部分中的第三个捕获组匹配)REGEX可能会成功完成。

  • PS:我正在学习有趣的东西,关于正则表达式,所以可能这个答案是完全错误的。 等待更好的答案。


    我并不完全理解你的问题,但是非贪婪的量词允许搜索模式的第一次出现。 使用pcretest,您可以在相同的输入上尝试贪婪和非贪婪的表单。

    非贪婪形式:

      re> /<a[s]+href[s]*=[s]*(["'])?(?(1)(.*?)1|([^s]+))/i
      data> <a href="ab"cd"
        0: <a href="ab"
        1: "
        2: ab
    

    贪婪的形式:

     re> /<a[s]+href[s]*=[s]*(["'])?(?(1)(.*)1|([^s]+))/i
     data> <a href="ab"cd"
        0: <a href="ab"cd"
        1: "
        2: ab"cd
    
    链接地址: http://www.djcxy.com/p/74797.html

    上一篇: How exactly do the lazy quantifiers work in PCRE?

    下一篇: NFA DFA and Regex to Transition Table