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

时间:2018-09-19 14:38:21

标签: c regex

我有一个c程序,无法使正则表达式匹配按我想要的方式工作。基本上,我想将testStr中的第一个字符(W或M)与第二个匹配项(TESTY.LOG)的日志文件名进行匹配。这是我到目前为止的内容:

#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] = '\0';
  }
}

在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中使用了regex,但是在ANSI C中是regex的新手。我觉得这里缺少基本知识。

1 个答案:

答案 0 :(得分:2)

匹配0是整个正则表达式(Perl的$1, $2, …)匹配的字符串的一部分。 i >的匹配 i > 0是与捕获编号 i 对应的匹配部分,与Perl的^([W|M])[[:space:]]([A-Z|0-9|\.]{1,})[[:space:]]*$ 相同。您有两次捕获,因此您应该期待三场比赛。但是您将MAX_MATCH指定为2,因此最后一个匹配项将被丢弃。


还有正则表达式

[W|M]

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

反斜杠是无关紧要的,因为它仅转义字符串文字中的,而不必转义。如果编译时启用了警告{1,},则C编译器可能会警告您转义序列不合法。如果您实际上已将反斜杠传递给regex库,则它将把它解释为字符类的另一个可能的匹配。

此外,在Perl和Posix Extended RE中,+都可以方便地写为reti = regcomp(&regex, "^([WM])[[:space:]]([A-Z0-9.]+)[[:space:]]*$", REG_EXTENDED)

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

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

您也可以使用

{{1}}