1

在集成到我的代码之前,我正在为 fnmatch 编写一个基本测试。这是测试:

int main (int argc, char *argv[])
{
    for (int i = 2; i < argc; i++)
        if (!fnmatch(argv[1], argv[i], 0))
            printf("%s matches %s\n", argv[i], argv[1]);
        else
            printf("%s doesn't matches %s\n", argv[i], argv[1]);
    return EXIT_SUCCESS;
}

我将其编译为test并运行以下命令:

$ ./test a*b? a ab aa acb abc aabc acbc aaaaaaaaaaaaaaab aaaaaaaaaaaaaaaba abb aabb

扩展输出:

a doesn't matches a*b?
ab matches a*b?
aa doesn't matches a*b?
acb matches a*b?
abc matches a*b?
aabc matches a*b?
acbc matches a*b?
aaaaaaaaaaaaaaaba matches a*b?
aaaaaaaaaaaaaaab matches a*b?
abb matches a*b?
aabb matches a*b? 

实际输出:

a doesn't matches a*b?
ab doesn't matches a*b?
aa doesn't matches a*b?
acb doesn't matches a*b?
abc matches a*b?
aabc matches a*b?
acbc matches a*b?
aaaaaaaaaaaaaaab doesn't matches a*b?
aaaaaaaaaaaaaaaba matches a*b?
abb matches a*b?
aabb matches a*b?

问题是'?元字符无法匹配 0 个字符(恰好需要一个)。

有谁知道它为什么会这样以及如何解决它?

先感谢您。

4

2 回答 2

2

这是预期的行为。Posix glob 匹配?单个字符,而不是空组。请参阅全局匹配

?可用于匹配正则表达式中的空组,但是 - 它匹配零个或一个匹配项。

于 2021-06-30T19:44:41.423 回答
1

如果使用带有 glibc 实现的 Linux 操作系统fnmatch(),您可以使用该FNM_EXTMATCH标志来启用ksh/bash样式扩​​展通配符,其中?(pattern)匹配模式1 或 0 次。使用它,?(?)将匹配任何字符的 1 或 0 个实例。

例子:

// Define before any includes to get FNM_EXTMATCH
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <fnmatch.h>

int main (int argc, char *argv[])
{
    for (int i = 2; i < argc; i++)
        if (fnmatch(argv[1], argv[i], FNM_EXTMATCH) == 0)
            printf("%s matches %s\n", argv[i], argv[1]);
        else
            printf("%s doesn't match %s\n", argv[i], argv[1]);
    return EXIT_SUCCESS;
}

和用法(提示:将模式放在引号中以防止您的 shell 尝试扩展它):

$ ./test  "a*b?(?)" a ab aa acb abc aabc acbc aaaaaaaaaaaaaaab aaaaaaaaaaaaaaaba abb aabb
a doesn't match a*b?(?)
ab matches a*b?(?)
aa doesn't match a*b?(?)
acb matches a*b?(?)
abc matches a*b?(?)
aabc matches a*b?(?)
acbc matches a*b?(?)
aaaaaaaaaaaaaaab matches a*b?(?)
aaaaaaaaaaaaaaaba matches a*b?(?)
abb matches a*b?(?)
aabb matches a*b?(?)
于 2021-06-30T21:11:46.473 回答