如何使用正则表达式捕获一个组?

33
我正在尝试使用正则表达式从另一个字符串中提取一个字符串。我正在使用POSIX正则表达式函数(regcomp, regexec ...),但是我无法捕获一个组...
例如,让模式简单点,如"MAIL FROM:<(.*)>"(带有REG_EXTENDED cflags)
我想捕获在'<'和'>'之间的所有内容。
我的问题是regmatch_t给出整个模式(MAIL FROM:<...>)的边界,而不仅仅是圆括号内的内容...
我错过了什么吗?
提前感谢,
编辑:一些代码
#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 ($)

解决方案:

如RarrRarrRarr所说,索引确实在pmatch[1].rm_sopmatch[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个回答

31

这里是一个演示捕获多个组的代码示例。

你可以看到,组“0”是整个匹配内容,而后续的组是括号内的部分。

请注意,这只会捕获源字符串中的第一个匹配项。这里有一个版本可以捕获多个匹配和多个组。

#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

[%2u-%2u] should be [%2llu-%2llu] to avoid warning format specifies type 'unsigned int' but the argument has type 'regoff_t' (aka 'long long') - coterobarros

13

pmatch数组的第0个元素将包含匹配整个字符串的边界,正如您所注意到的那样。在您的示例中,您需要关注索引1处的regmatch_t,而不是索引0处的regmatch_t,以获取有关由子表达式匹配的字符串的信息。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接