C 语言正则表达式匹配字符串的多个部分



我有一个c程序,我无法让正则表达式匹配以我想要的方式工作。基本上,我想匹配testStr中的第一个字符(W 或 M(和日志文件的名称作为第二个匹配项 (TESTY.日志(。 这是我到目前为止所拥有的:

#include    <stdio.h>
#include    <stdlib.h>
#include    <regex.h>
#define     MAX_MATCHES 2
.....
char testStr[20]="W TESTY.LOG ";
char temp[100];
int reti;
regex_t regex;
regmatch_t matches[MAX_MATCHES];
int i;
int numchars;
/* Compile regular expression */
reti = regcomp(&regex, "^([W|M])[[:space:]]([A-Z|0-9|.]{1,})[[:space:]]*$", REG_EXTENDED);
/* Execute regular expression */
reti = regexec(&regex, testStr, MAX_MATCHES, matches, 0);
if (!reti) {
for (i=0; i < MAX_MATCHES; i++) {
numchars = (int)matches[i].rm_eo - (int)matches[i].rm_so;
strncpy(temp,testStr+matches[i].rm_so,numchars);
temp[numchars] = '';
}
}

当我在 gdb 中运行它时,我看到以下匹配项:

(gdb) display matches 1: matches = {{rm_so = 0, rm_eo = 15}, {rm_so = 0, rm_eo = 1}}

2: temp = "W TESTY.LOG"

2: temp = "W"

所以,我得到了第一个字符,但我没有得到第二个匹配的日志文件名。 我在perl中使用正则表达式,但我是ansi c中的正则表达式的新手。 我觉得我在这里错过了一些基本的东西。

匹配0 是整个正则表达式匹配的字符串部分(Perl 的$&(。匹配 i 对于 i> 0 是匹配中与捕获编号i对应的部分,与 Perl$1, $2, …相同。您有两个捕获,因此您应该期待三场比赛。但是您将MAX_MATCH指定为 2,因此将放弃最后一个匹配项。


此外,正则表达式

^([W|M])[[:space:]]([A-Z|0-9|.]{1,})[[:space:]]*$

有点奇怪。我认为你应该重读关于正则表达式中字符类的文档——在这种情况下,它在 Perl 中和在 Posix 扩展 RE 中是一样的。[W|M]匹配三个字符W|M中的任何一个。同样,[A-Z|0-9|.]{1,}匹配一个或多个字母、数字、字符|或字符 ..

反斜杠无关紧要,因为它只转义字符串文本中的.,其中转义是不必要的。如果您在启用警告的情况下进行编译,-Wall,您的 C 编译器可能会警告您转义序列不合法。如果您实际上已将反斜杠传递给正则表达式库,它会将其解释为字符类的另一个可能匹配项。

此外,{1,}可以方便地写成+,无论是在Perl还是在Posix Extended REs中。

简而言之,您可能想要的是:

reti = regcomp(&regex, "^([WM])[[:space:]]([A-Z0-9.]+)[[:space:]]*$", REG_EXTENDED)

您也可以使用

reti = regcomp(&regex, "^([WM])[[:space:]]([[:alnum:].]+)[[:space:]]*$", REG_EXTENDED)

最新更新