使用Shell通配符模式匹配字符串
问题
希望使用与在Unix shell中常用的相同通配符模式匹配文本(例如,.py,Dat [0-9].csv等)。
方案
fnmatch模块提供了两个函数fnmatch和fnmatchcase。唯一的区别是是否区分字母大小写。示例如下:
>>> from fnmatch import fnmatch, fnmatchcase
>>> fnmatch('foo.txt', '*.txt')
True
>>> fnmatch('foo.txt', '?oo.txt')
True
>>> fnmatch('Dat45.csv', 'Dat[0-9]*')
True
>>> names = ['Dat1.csv', 'Dat2.csv', 'config.ini', 'foo.py']
>>> [name for name in names if fnmatch(name, 'Dat*.csv')]
['Dat1.csv', 'Dat2.csv']
>>>
此模块提供对Unix shell样式通配符的支持,这些通配符与正则表达式(在re模块中)不同。 shell样式通配符中使用的特殊字符是:
Pattern | Meaning |
---|---|
* | matches everything |
? | matches any single character |
[seq] | matches any character in seq |
[!seq] | matches any character not in seq |
这些函数经常被忽视的一个特性是它们可能用于非文件名字符串的数据处理。 例如,假设有一个街道地址列表,如下所示:
addresses = [
'5412 N CLARK ST',
'1060 W ADDISON ST',
'1039 W GRANVILLE AVE',
'2122 N CLARK ST',
'4802 N BROADWAY',
]
>>> from fnmatch import fnmatchcase
>>> [addr for addr in addresses if fnmatchcase(addr, '* ST')]
['5412 N CLARK ST', '1060 W ADDISON ST', '2122 N CLARK ST']
>>> [addr for addr in addresses if fnmatchcase(addr, '54[0-9][0-9] *CLARK*')]
['5412 N CLARK ST']
>>>
总结
fnmatch执行的匹配介于简单字符串方法和正则表达式之间。 如果只是尝试提供一种在数据处理操作中允许使用通配符的简单机制,那么它通常是一种合理的解决方案。
如果实际上尝试编写与文件名匹配的代码,请改用glob模块。