代码之家  ›  专栏  ›  技术社区  ›  Sylvain

如何用regex捕获组?

  •  21
  • Sylvain  · 技术社区  · 14 年前

    我正在尝试使用regex从另一个字符串中提取字符串。 我正在使用posix regex函数( regcomp, regexec …),我没能抓到一个组…

    例如,让模式变得像 "MAIL FROM:<(.*)>"
    REG_EXTENDED cFLAGS)

    我要捕获“<”和“>”之间的所有内容

    我的问题是 regmatch_t 给出了整个模式的边界(邮件来自:<…>)而不是括号之间的内容…

    我错过了什么?

    事先谢谢,

    编辑:一些代码

    #define SENDER_REGEX "MAIL FROM:<(.*)>"
    
    int main(int ac, char **av)
    {
      regex_t regex;
      int status;
      regmatch_t pmatch[1];
    
      if (regcomp(&regex, SENDER_REGEX, REG_ICASE|REG_EXTENDED) != 0)
        printf("regcomp error\n");
      status = regexec(&regex, av[1], 1, pmatch, 0);
      regfree(&regex);
      if (!status)
          printf(  "matched from %d (%c) to %d (%c)\n"
                 , pmatch[0].rm_so
                 , av[1][pmatch[0].rm_so]
                 , pmatch[0].rm_eo
                 , av[1][pmatch[0].rm_eo]
                );
    
      return (0);
    }
    

    输出:

    $./a.out "012345MAIL FROM:<abcd>$"
    matched from 6 (M) to 22 ($)
    

    解决方案:

    正如拉rrarrrar所说,这些指数确实在 pmatch[1].rm_so pmatch[1].rm_eo
    因此 regmatch_t pmatch[1]; 变成 regmatch_t pmatch[2];
    regexec(&regex, av[1], 1, pmatch, 0); 变成 regexec(&regex, av[1], 2, pmatch, 0);

    谢谢:)

    2 回复  |  直到 12 年前
        1
  •  9
  •   RarrRarrRarr    14 年前

    正如您注意到的,regmatch结构的pmatch数组的第0个元素将包含匹配的整个字符串的边界。在您的示例中,您对索引1而不是索引0处的regmatch_t感兴趣,以便通过子表达式获取有关字符串匹配的信息。

    如果您需要更多帮助,请尝试编辑您的问题以包含实际的小代码示例,以便人们更容易发现问题。

        2
  •  18
  •   Ian Mackinnon    12 年前

    下面是一个代码示例,演示如何捕获多个组。

    您可以看到组“0”是完全匹配的,后面的组是圆括号中的部分。

    请注意,这将只捕获源字符串中的第一个匹配项。 Here's a version that captures multiple groups in multiple matches .

    #include <stdio.h>
    #include <string.h>
    #include <regex.h>
    
    int main ()
    {
      char * source = "___ abc123def ___ ghi456 ___";
      char * regexString = "[a-z]*([0-9]+)([a-z]*)";
      size_t maxGroups = 3;
    
      regex_t regexCompiled;
      regmatch_t groupArray[maxGroups];
    
      if (regcomp(&regexCompiled, regexString, REG_EXTENDED))
        {
          printf("Could not compile regular expression.\n");
          return 1;
        };
    
      if (regexec(&regexCompiled, source, maxGroups, groupArray, 0) == 0)
        {
          unsigned int g = 0;
          for (g = 0; g < maxGroups; g++)
            {
              if (groupArray[g].rm_so == (size_t)-1)
                break;  // No more groups
    
              char sourceCopy[strlen(source) + 1];
              strcpy(sourceCopy, source);
              sourceCopy[groupArray[g].rm_eo] = 0;
              printf("Group %u: [%2u-%2u]: %s\n",
                     g, groupArray[g].rm_so, groupArray[g].rm_eo,
                     sourceCopy + groupArray[g].rm_so);
            }
        }
    
      regfree(&regexCompiled);
    
      return 0;
    }
    

    输出:

    Group 0: [ 4-13]: abc123def
    Group 1: [ 7-10]: 123
    Group 2: [10-13]: def