【问题标题】:Strange answer using PCRE Regex使用 PCRE 正则表达式的奇怪答案
【发布时间】:2013-03-06 11:07:23
【问题描述】:

我正在使用 C (http://www.pcre.org/) 中的 PCRE 正则表达式库来解析和匹配我的 HTML 字符串。为了简化我的问题,假设我得到了源字符串:"aaa: bbbb:",以及我的模式:a(.*?):|b( .*?):,符号?表示是非贪婪匹配,所以答案应该是两个匹配:一个是"aaa:"和另一个“bbbb:”

然后我编程:

char *src = "aaa:  bbbb:";
char *pattern = "a(.*?):|b(.*?):";
pcre *re = NULL;

//---missing out---

re = pcre_compile(pattern,  // pattern,  
                  0,            // options,   
                  &error,       // errptr,   
                  &erroffset,   // erroffset,  
                  NULL);        // tableptr, 
while (
      (rc = pcre_exec(re,     // regex ptr,   
               NULL,          // extra arg,   
               src,           // subject,   
               strlen(src),   // length,   
               0,             // startoffset,   
               0,             // options,   
               ovector,       // ovector,   
               OVECCOUNT)     // ovecsize,   
      )!=PCRE_ERROR_NOMATCH)  
    {
       printf("\nOK, string has matched ...there are %d matchups\n\n",rc); //  
       for (i = 0; i < rc; i++)
       {
            char *substring_start = src + ovector[2*i];
            int substring_length = ovector[2*i+1] - ovector[2*i];
            printf("$%2d: %.*s length: %d\n", i, substring_length, substring_start,substring_length);
       }
       src = src + ovector[1];  // to move the src pointer to the end offset of current matchup
       if (!src) break;
    }
pcre_free(re);

我得到了结果:

Source : aaa:  bbbb:
Pattern: "a(.*?):|b(.*?):"

OK, string has matched ...there are 2 matches

$ 0: aaa: length: 4
$ 1: aa length: 2 

OK, string has matched ...there are 3 matches

$ 0: bbbb: length: 5
$ 1:  length: 0
$ 2: bbb length: 3

我想知道,我是如何得到答案的 "$ 1: length: 0"

//--------------------------------------------- -------------------------------------------------------

@Jonathan Leffler 我认为你的回答是对的。

刚刚试了

Source: "aaa: bbb: ccc:"
Pattern: "c(.+?):|a(.+?):|b(.+?):"

得到的结果是这样的:

$ 0: aaa: length: 4
$ 1:  length: 0
$ 2: aa length: 2

$ 0: bbbb: length: 5
$ 1:  length: 0
$ 2:  length: 0
$ 3: bbb length: 3

$ 0: cccc: length: 5
$ 1: ccc length: 3

这反过来证明了你的答案:

当找到匹配时,正则表达式的捕获停止,所以aaa:在尝试匹配c(.+?):后被a(.+?):捕获,结果的第一行显示整个字符串,#2显示结果与替代 c(.+?): 匹配的偏移量

对于 b(.+?),它最终在正则表达式中被捕获,这解释了两个 length : 0

对于c(.+?),一开始就被抓到了,所以没有length : 0

【问题讨论】:

  • 您能否扩充示例源代码以便编译?
  • 可能是因为你使用*而不是+

标签: c regex pcre


【解决方案1】:

正则表达式中有两个捕获,每个替代项中都有一个。但是,捕获是从左到右编号的。在第二种情况下,第一个($1)捕获为空;它匹配的内容中没有a,所以第一个捕获是空的;第二个 ($2) 捕获包含您所期望的 b

几乎更令人惊讶的是,在第一次匹配时没有为第二次捕获指定任何内容。如果没有数据,我猜这些捕获是空的。

【讨论】:

    【解决方案2】:

    * 表示任意数量的字符,包括零。这意味着它匹配“无”。应改用+ 字符,表示“至少匹配1”。

    【讨论】:

    • 它没有回答为什么它在那里的问题。
    【解决方案3】:

    尝试使用模式char *pattern = "a+?:|b+?:";

    编辑注意到只有"a+:|b+:" 也可以工作。

    【讨论】:

    • 这个问题询问它为什么会发生,而不是对正则表达式的建议,这可能是一个显示奇怪的例子。
    【解决方案4】:

    图案:

    a(.*?):
    

    此模式意味着查找未捕获的“a”,然后捕获任意数量的任何内容,修改为返回最小的匹配模式,然后是未捕获的“:”。

    如果考虑字符串:

    aaa:
    

    现在想想冒号前的最后一个“a”:

    a:
    

    它与模式匹配 - 一个“a”,后面没有任何内容,然后是一个冒号。 “什么都没有”被捕获,这就是你得到零长度结果的原因。

    【讨论】:

    • 第二次匹配捕获的整体字符串为bbbb;涉及a: 的解释显然不适用。
    • 抱歉,关于我的实际问题,我没有给出一个很好的例子,但是您的回答无法解释为什么aaa: 的结果中有length:0
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 2014-08-02
    • 1970-01-01
    • 1970-01-01
    • 2018-06-03
    • 1970-01-01
    相关资源
    最近更新 更多