在C语言中无法匹配正则表达式

5

我遇到了以下正则表达式的问题:

 prefix:\w+,\w+,\s*-?[0-9]{1,4}\s*,\s*-?[0-9]{1,4}\s*,\s*-?[0-9]{1,4}\s*,(?:\w+)

匹配字符串如下:

prefix:string,string,-100,100,0,string

我在我的C代码中无法匹配此字符串。至少我在一些在线工具上使用生成的正则表达式成功匹配。还有编译警告关于正则表达式中的"\"字符,所以我按照C编译器警告-未知转义序列使用正则表达式进行C程序中的解释进行了替换。编译警告修复后的正则表达式:

prefix:\\w+,\\w+,\\s*-?[0-9]{1,4}\\s*,\\s*-?[0-9]{1,4}\\s*,\\s*-?[0-9]{1,4}\\s*,(?:\\w+)

这是测试代码:

#include <stdio.h>
#include <regex.h>        
#include <stdlib.h>

#define REGEX "prefix:\\w+,\\w+,\\s*-?[0-9]{1,4}\\s*,\\s*-?[0-9]{1,4}\\s*,\\s*-?[0-9]{1,4}\\s*,(?:\\w+)"

const char *input = "prefix:string,string,-100,100,0,string";
int main(){

    int rc;

    regex_t regex;

    rc = regcomp(&regex, REGEX, 0);
    if (rc != 0) {
        fprintf(stderr, "Could not compile regex\n");
        exit(1);
    }

    rc = regexec(&regex, input, 0, NULL, 0);
    if (rc == 0) {
        printf("Match!\n");
        return 0;
    }
    else if (rc == REG_NOMATCH) {
        printf("No match\n");
        return -1;
    }
    else {
        perror("Error\n");
        exit(1);
    }

    return 0;
}

我使用的是gcc版本6.2.0 20161005 (Ubuntu 6.2.0-5ubuntu12)


由于这似乎是一个相当复杂的正则表达式,您可能需要使用REG_EXTENDED: “模式的默认正则表达式类型是基本正则表达式。应用程序可以使用REG_EXTENDED cflags标志指定扩展正则表达式。”(http://pubs.opengroup.org/onlinepubs/009695399/functions/regcomp.html) - Jongware
1
如果未转义限定符,则必须使用REG_EXTENDED。在BRE中,{n,m}应该被转义。我认为应该删除(?:)。请参见此C演示,返回Match - Wiktor Stribiżew
1
@RadLexus 我试过了,使用cflags参数指定此标志会导致regcomp失败。 - pbn
这很奇怪。即使是一个简单的正则表达式,比如 .{4} 和输入 aaaa 也无法匹配。我正在查看手册页面,表面上看起来你的代码没有问题... - Qix - MONICA WAS MISTREATED
@WiktorStribiżew 是的,使用 ( 替换 (?: 可以解决问题。我没有提到最后一个字符串是可选的,所以正则表达式也不同。此外,需要使用 REG_EXTENDED 才能使其正常工作。 - pbn
显示剩余2条评论
1个回答

7
你需要做两件事情:
  • 使用REG_EXTENDED标志来编译正则表达式(这样扩展的正则表达式风格(ERE)就会被启用),否则限制量词将需要转义,可能会出现其他潜在问题。
  • 移除非捕获组(?:...),因为POSIX不支持这种结构。
  • 要使\w+变为可选项,只需将(?:\w+)替换为\w*
使用
#define REGEX "prefix:\\w+,\\w+,\\s*-?[0-9]{1,4}\\s*,\\s*-?[0-9]{1,4}\\s*,\\s*-?[0-9]{1,4}\\s*,\\w*"
                                                                                                ^^^

然后

rc = regcomp(&regex, REGEX, REG_EXTENDED);
                            ^^^^^^^^^^^^

请查看C示例
此外,了解更多关于REG_EXTENDED启用的扩展正则表达式,以及POSIX括号表达式是学习BRE(基本正则表达式)和ERE风格之间差异的好资源。

始终如旧,一些相关文档链接将会很有帮助 :) - Qix - MONICA WAS MISTREATED
嗯,是的,在扩展正则表达式中,并没有说明不支持非捕获组,而且要使用{1,3}而不是\{1,3\},应该使用REG_EXTENDED标志。 - Wiktor Stribiżew
2
我添加了一些链接并修复了演示链接。 - Wiktor Stribiżew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接