C - regexec返回NOMATCH - 即使它应该?

时间:2017-02-09 23:43:04

标签: c regex c99

正则表达式模式需要匹配以下内容:

abc_xyz_0
abc_1025_01.29.00_xyz_0
abc_0302_42.01.00_xyz_0 

(abc和xyz之间的数字无关紧要)

所以我解析:

(abc_(\w+\.\d+\.\w+)?xyz_0)

我的代码:

regex_t r;
unsigned int maxGroups = 3;
regmatch_t groupArray[maxGroups];
char * to_match = "abc_0302_02.01.00_xyz_18 abc_0302_02.01.00_xyz_16 abc_0302_02.01.00_xyz_14 abc_0302_02.01.00_xyz_0 abc_0302_02.01.00_xyz_10 abc_0302_02.01.00_xyz_2"

if (0 != regcomp(&r, "(abc_(\\w+\\.\\d+\\.\\w+)?xyz_0)", REG_EXTENDED)) 
{
    //this does NOT get hit
    printf("regcomp failed")
}
else if(regexec(r, to_match, maxGroups, groupArray, REG_EXTENDED) == 0)
 { *never gets here* }
else
 { printf("regexec returned non-zero(No Matches)\n"); }

regfree(&r);

所以我的猜测是我有错误的正则表达式(对我上面定义的情况工作正常 - 我用regexpal.com确认),或者有些东西我不知道?

无论哪种方式,我都知道我很亲近,非常感谢你的帮助。

1 个答案:

答案 0 :(得分:1)

您复制到问题中的代码中有几个拼写错误(见下文),您只应将REG_EXTENDED传递给regcomp;唯一标记为regexec的标记为REG_NOTBOLREG_NOTEOL。 (有关详细信息,请参阅regexec manpage。)

然而,问题是Posix正则表达式,包括Gnu实现,没有实现非标准转义序列\d。如regex(7) manpage所示,模式可以包括:

  

a' \'其次是一个字符" ^。[$()| * +?{\" (将该角色与普通角色相匹配),

  

a' \'其次是任何其他角色(将该角色与普通角色相匹配,就好像' \'不存在一样)

请注意,在任何一种情况下,\的唯一影响是使后续字符与普通字符匹配。虽然regcomp的Gnu实现确实将\w识别为字符类,但Posix不需要该行为,而其他实现可能不会这样做。 (它也没有记录,所以它可能并不总是有效。)它无法识别\d

如果您使用Posix正则表达式,则应使用Posix标准字符类,因此正则表达式字符串应为:

"(abc_([[:alnum:]_]+\\.[[:digit:]]+\\.[[:alnum:]_]+)?xyz_0)"

您将在上一个链接的正则表格联机帮助页中找到Posix命名字符类的列表(或者通过键入man 7 regex,假设您已经安装了标准库文档,强烈建议这样做。)

我在代码中验证了这一点,在char * to_match =...末尾添加了缺少的分号,并在调用r时将&r更改为regexec

请注意,很少有在线正则表达式资源实现Posix正则表达式规范;例如,http://regexpal.com仅提供PCRE和Javascript样式正则表达式的选项。

每次调用regexec时,根据man 7 regex中描述的固定算法,您将获得传递给它的字符串中的第一个匹配项:

  

如果RE可以匹配a的多个子字符串          给定字符串,RE匹配字符串中最早开始的字符串。          如果RE可以匹配从该点开始的多个子字符串,          它匹配时间最长。 Subexpressions也是最长的          可能的子串,受限于整个匹配          尽可能长,子表达式在早期开始          RE优先于稍后开始的。注意更高级别          因此,子表达式优先于它们的低级组件          子表达式。

如果要在同一个字符串中查找模式的多个实例,则需要在循环中调用regexec。每次循环时,都会为它提供上一次匹配中第一个不匹配字节的地址(即string + matches[0].rm_eo),直到它报告不再匹配为止。如果您在匹配中依赖^个锚点,则需要将REG_NOTBOL标记的正确值传递给每次regexec的调用。