正则表达式模式需要匹配以下内容:
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确认),或者有些东西我不知道?
无论哪种方式,我都知道我很亲近,非常感谢你的帮助。
答案 0 :(得分:1)
您复制到问题中的代码中有几个拼写错误(见下文),您只应将REG_EXTENDED
传递给regcomp
;唯一标记为regexec
的标记为REG_NOTBOL
和REG_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
的调用。