使用PCRE Regex的奇怪答案

时间:2013-03-06 11:07:24

标签: c regex pcre

我在C(http://www.pcre.org/)中使用PCRE正则表达式lib来解析和匹配我的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:长度: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:a(.+?):会抓取c(.+?):,结果的第一行显示整个字符串, #2显示结果偏移量与替代c(.+?):

匹配

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

对于c(。+?),它首先被捕获,因此没有length : 0

4 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

*表示任何数字,包括零个字符。这意味着它匹配“没有”。应该使用+字符,表示“匹配至少1”。

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

模式:

a(.*?):

这种模式意味着寻找一个未捕获的'a',然后捕获任何数量的任何东西,修改为返回最小的匹配模式,然后是未捕获的':'。

如果你考虑字符串:

aaa:

现在想想结肠前的最后一个'a':

a:

它匹配模式 - 一个'a',后面跟着什么,然后是一个冒号。捕获'无',这就是为什么你获得零长度的结果。