Regex 懒惰量词在PCRE中究竟是如何工作的?

Regex 懒惰量词在PCRE中究竟是如何工作的?,regex,nfa,Regex,Nfa,一点背景知识:我正在实现一个正则表达式匹配引擎(NFA),它应该支持PCRE兼容模式(我的意思是它应该捕获具有与PCRE相同偏移量的子表达式) PCRE的testinput1中有一个测试,我不能完全理解。它测试惰性量词 所以,正则表达式是 /<a[\s]+href[\s]*=[\s]* # find <a href= ([\"\'])? # find single or double quote (?(1) (.*?)

一点背景知识:我正在实现一个正则表达式匹配引擎(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

因此,关于PCRE回溯特定行为的建议很可能是错误的…

首先,我只是REGEX领域的初学者。因此,如果这个答案是错误的,或者如果我误解了这个问题,我很抱歉

阅读本书中的定义:

(?(1)then | else)是检查第一个捕获组 已经匹配了一些东西。如果有,正则表达式引擎将尝试匹配 那么。如果到目前为止捕获组还没有参加比赛, 尝试其他部分


  • 关于这个主题:
    我不完全理解您的问题,但是非贪婪量词允许搜索到模式的第一个出现。使用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
    

    re>/我曾经犯过一个错误,就是看了看它是如何完成的。吓人的!就我所见,完整的PCRE需要堆栈评估模型,而不是自动机理论模型。使用基于自动机的方法最接近的可能是PostgreSQL和Tcl中使用的重新引擎,但这真的很复杂。感谢您的快速响应。但这似乎不是一种回溯特定行为(见编辑),可以使用自动机实现(尽管我知道TRE未能通过AT&T测试数据存储库中的POSIX合规性测试,因此,这种行为可能是一种“错误”)。
    
    <a href="abcd
    
    #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)
    
      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