我有一个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(®ex, "^([W|M])[[:space:]]([A-Z|0-9|.]{1,})[[:space:]]*$", REG_EXTENDED);
/* Execute regular expression */
reti = regexec(®ex, 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(®ex, "^([WM])[[:space:]]([A-Z0-9.]+)[[:space:]]*$", REG_EXTENDED)
您也可以使用
reti = regcomp(®ex, "^([WM])[[:space:]]([[:alnum:].]+)[[:space:]]*$", REG_EXTENDED)