2.3 用Shell通配符匹配字符串

2018-02-24 15:26 更新

問題

你想使用Unix Shell中常用的通配符(比如.py, Dat[0-9].csv等)去匹配文本字符串

解決方案

fnmatch模塊提供了兩個(gè)函數(shù)—— fnmatch()fnmatchcase() ,可以用來實(shí)現(xiàn)這樣的匹配。用法如下:

>>> 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']
>>>

fnmatch() 函數(shù)使用底層操作系統(tǒng)的大小寫敏感規(guī)則(不同的系統(tǒng)是不一樣的)來匹配模式。比如:

>>> # On OS X (Mac)
>>> fnmatch('foo.txt', '*.TXT')
False
>>> # On Windows
>>> fnmatch('foo.txt', '*.TXT')
True
>>>

如果你對這個(gè)區(qū)別很在意,可以使用 fnmatchcase() 來代替。它完全使用你的模式大小寫匹配。比如:

>>> fnmatchcase('foo.txt', '*.TXT')
False
>>>

這兩個(gè)函數(shù)通常會(huì)被忽略的一個(gè)特性是在處理非文件名的字符串時(shí)候它們也是很有用的。比如,假設(shè)你有一個(gè)街道地址的列表數(shù)據(jù):

addresses = [
    '5412 N CLARK ST',
    '1060 W ADDISON ST',
    '1039 W GRANVILLE AVE',
    '2122 N CLARK ST',
    '4802 N BROADWAY',
]

你可以像這樣寫列表推導(dǎo):

>>> 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() 函數(shù)匹配能力介于簡單的字符串方法和強(qiáng)大的正則表達(dá)式之間。如果在數(shù)據(jù)處理操作中只需要簡單的通配符就能完成的時(shí)候,這通常是一個(gè)比較合理的方案。

如果你的代碼需要做文件名的匹配,最好使用glob模塊。參考5.13小節(jié)。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號