否定一个fnmatch模式

5
考虑这个模式:*.py。它匹配所有以 py 扩展名结尾的路径。那么,是否可能找到一个可以匹配所有其它内容的模式呢?
我认为这个可以: *[!.][!p][!y],但是显然fnmatch.fnmatch总是返回False
我想避免使用正则表达式。我知道我可以用它们,但在这种情况下不可能。

请注意,fnmatch 并不总是针对您提出的模式返回 Falsefnmatch.fnmatch("blah","*[!.][!p][!y]") 返回 True。您可能观察到的行为是,只要倒数第三个字符是 .*[!.][!p][!y] 必须返回 False - Kyle Strand
3个回答

5
我个人更喜欢正则表达式,但如果您更喜欢fnmatch,您可以这样做:
if fnmatch.fnmatch(file, '*[!p][!y]'):
        print(file)

1
是的,我知道我可以像这样做一些事情。但实际上我正在寻找一种模式,因为我必须将其用于使用fnmatch的程序的--exclude选项中。 - rubik
我已更新了模式 -- 但我建议您考虑重新思考您的模式。快速扫描fnmatch和glob的源代码显示它们在底层都使用正则表达式。 - user590028
对我来说没问题... [f for f in os.listdir('.') if fnmatch.fnmatch(f, '*[!py]')] == ['admin.pyc', 'ajax.pyc', ...] - thebjorn
4
*[!p][!y] 匹配任何不以 p 作为倒数第二个字符且不以 y 作为最后一个字符的内容。例如,扩展名为 .pl 的 Perl 脚本将被排除在外。 - Kyle Strand
1
@KyleStrand,所接受的答案正则表达式'* [!p] [!y]'是错误的,因为它也排除了像.plhy这样的内容。有没有一种方法可以排除整个句子而不是单个字符? - murt
显示剩余9条评论

3
我认为唯一完全正确的答案是生成不需要文件列表,然后找到此列表与完整(未过滤)文件列表之间的差异。 (可以在此处使用set查看此技术:https://dev59.com/Ql7Va4cB1Zd3GeqPL6yW#8645326fnmatch 模块中似乎没有内置选项来否定搜索模式。
有关逐个字符否定不起作用的示例,请参阅我的评论user590028的答案。

有趣的方法,似乎也是最正确的方法。谢谢! - rubik

0
如果files是一个文件列表,那么这段代码将使用fnmatch.filter排除所有与*.py模式匹配的文件。这应该是正确的答案。
exclude = '*.py'
for f in fnmatch.filter(files, exclude):
    files.remove(f)

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