14

现在,当我想返回 str 中的所有匹配位置时,例如:

abcd123abcd123abcd

假设我想得到所有的“abcd”,我必须使用regexec(),得到第一个位置:0、3,那么我将使用:

123abcd123abcd

作为再次使用 regexec() 的新字符串,依此类推。我阅读了有关 regexec() 的手册,它说:

int regexec(const regex_t *preg, const char *string, size_t nmatch,
               regmatch_t pmatch[], int eflags);
nmatch and pmatch are used to provide information regarding the location of any 
matches.

但为什么这不起作用?这是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <regex.h>

int main(int argc, char **argv)
{
   int i = 0;
   int res;
   int len;
   char result[BUFSIZ];
   char err_buf[BUFSIZ];
   char* src = argv[1];  

   const char* pattern = "\\<[^,;]+\\>";
   regex_t preg;

   regmatch_t pmatch[10];

   if( (res = regcomp(&preg, pattern, REG_EXTENDED)) != 0)
   {
      regerror(res, &preg, err_buf, BUFSIZ);
      printf("regcomp: %s\n", err_buf);
      exit(res);
   }

   res = regexec(&preg, src, 10, pmatch, REG_NOTBOL);
   //~ res = regexec(&preg, src, 10, pmatch, 0);
   //~ res = regexec(&preg, src, 10, pmatch, REG_NOTEOL);
   if(res == REG_NOMATCH)
   {
      printf("NO match\n");
      exit(0);
   }
   for (i = 0; pmatch[i].rm_so != -1; i++)
   {
      len = pmatch[i].rm_eo - pmatch[i].rm_so;
      memcpy(result, src + pmatch[i].rm_so, len);
      result[len] = 0;
      printf("num %d: '%s'\n", i, result);
   }
   regfree(&preg);
   return 0;
}

./regex 'hello, world'

输出:

num 0: 'hello'

这是我的尊重输出:

num 0: 'hello'
num 1: 'world'
4

1 回答 1

18

regexec执行正则表达式匹配。一旦找到匹配项,regexec 将返回零(即成功匹配)。该参数pmatch将包含有关该匹配的信息。第一个数组索引(即零)将包含整个匹配项,后续数组索引包含有关捕获组/子表达式的信息。

展示:

const char* pattern = "(\\w+) (\\w+)";

在“hello world”上匹配将输出:

num 0: 'hello world'  - entire match
num 1: 'hello'        - capture group 1
num 2: 'world'        - capture group 2

(看到它在行动

在大多数正则表达式环境中,您寻求的行为可以通过使用全局修饰符获得:/g。Regexec 不提供此修饰符作为标志,也不支持修饰符。因此,当 regexec 从上一个匹配项的最后一个字符开始返回零时,您必须循环以获取所有匹配项

使用 PCRE 库(著名的正则表达式 C 库)也无法使用全局修饰符。PCRE 手册页对此有这样的说法:

通过使用适当的参数多次调用 pcre_exec(),您可以模仿 Perl 的 /g 选项

于 2013-05-09T20:00:55.723 回答