W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
你想匹配或者搜索特定模式的文本
如果你想匹配的是字面字符串,那么你通常只需要調(diào)用基本字符串方法就行,比如 str.find()
, str.endswith()
, str.startswith()
或者類似的方法:
>>> text = 'yeah, but no, but yeah, but no, but yeah'
>>> # Exact match
>>> text == 'yeah'
False
>>> # Match at start or end
>>> text.startswith('yeah')
True
>>> text.endswith('no')
False
>>> # Search for the location of the first occurrence
>>> text.find('no')
10
>>>
對于復(fù)雜的匹配需要使用正則表達式和re模塊。為了解釋正則表達式的基本原理,假設(shè)你想匹配數(shù)字格式的日期字符串比如”11/27/2012”,你可以這樣做:
>>> text1 = '11/27/2012'
>>> text2 = 'Nov 27, 2012'
>>>
>>> import re
>>> # Simple matching: \d+ means match one or more digits
>>> if re.match(r'\d+/\d+/\d+', text1):
... print('yes')
... else:
... print('no')
...
yes
>>> if re.match(r'\d+/\d+/\d+', text2):
... print('yes')
... else:
... print('no')
...
no
>>>
如果你想使用同一個模式去做多次匹配,你應(yīng)該先將模式字符串預(yù)編譯為模式對象。比如:
>>> datepat = re.compile(r'\d+/\d+/\d+')
>>> if datepat.match(text1):
... print('yes')
... else:
... print('no')
...
yes
>>> if datepat.match(text2):
... print('yes')
... else:
... print('no')
...
no
>>>
match()
總是從字符串開始去匹配,如果你想查找字符串任意部分的模式出現(xiàn)位置,使用 findall()
方法去代替。比如:
>>> text = 'Today is 11/27/2012. PyCon starts 3/13/2013.'
>>> datepat.findall(text)
['11/27/2012', '3/13/2013']
>>>
在定義正則式的時候,通常會利用括號去捕獲分組。比如:
>>> datepat = re.compile(r'(\d+)/(\d+)/(\d+)')
>>>
捕獲分組可以使得后面的處理更加簡單,因為可以分別將每個組的內(nèi)容提取出來。比如:
>>> m = datepat.match('11/27/2012')
>>> m
<_sre.SRE_Match object at 0x1005d2750>
>>> # Extract the contents of each group
>>> m.group(0)
'11/27/2012'
>>> m.group(1)
'11'
>>> m.group(2)
'27'
>>> m.group(3)
'2012'
>>> m.groups()
('11', '27', '2012')
>>> month, day, year = m.groups()
>>>
>>> # Find all matches (notice splitting into tuples)
>>> text
'Today is 11/27/2012. PyCon starts 3/13/2013.'
>>> datepat.findall(text)
[('11', '27', '2012'), ('3', '13', '2013')]
>>> for month, day, year in datepat.findall(text):
... print('{}-{}-{}'.format(year, month, day))
...
2012-11-27
2013-3-13
>>>
findall()
方法會搜索文本并以列表形式返回所有的匹配。如果你想以迭代方式返回匹配,可以使用 finditer()
方法來代替,比如:
>>> for m in datepat.finditer(text):
... print(m.groups())
...
('11', '27', '2012')
('3', '13', '2013')
>>>
關(guān)于正則表達式理論的教程已經(jīng)超出了本書的范圍。不過,這一節(jié)闡述了使用re模塊進行匹配和搜索文本的最基本方法。核心步驟就是先使用 re.compile()
編譯正則表達式字符串,然后使用 match()
, findall()
或者 finditer()
等方法。
當(dāng)寫正則式字符串的時候,相對普遍的做法是使用原始字符串比如 r'(\d+)/(\d+)/(\d+)'
。這種字符串將不去解析反斜杠,這在正則表達式中是很有用的。如果不這樣做的話,你必須使用兩個反斜杠,類似 '(\\d+)/(\\d+)/(\\d+)'
。
需要注意的是 match()
方法僅僅檢查字符串的開始部分。它的匹配結(jié)果有可能并不是你期望的那樣。比如:
>>> m = datepat.match('11/27/2012abcdef')
>>> m
<_sre.SRE_Match object at 0x1005d27e8>
>>> m.group()
'11/27/2012'
>>>
如果你想精確匹配,確保你的正則表達式以$結(jié)尾,就像這么這樣:
>>> datepat = re.compile(r'(\d+)/(\d+)/(\d+)$')
>>> datepat.match('11/27/2012abcdef')
>>> datepat.match('11/27/2012')
<_sre.SRE_Match object at 0x1005d2750>
>>>
最后,如果你僅僅是做一次簡單的文本匹配/搜索操作的話,可以略過編譯部分,直接使用re模塊級別的函數(shù)。比如:
>>> re.findall(r'(\d+)/(\d+)/(\d+)', text)
[('11', '27', '2012'), ('3', '13', '2013')]
>>>
但是需要注意的是,如果你打算做大量的匹配和搜索操作的話,最好先編譯正則表達式,然后再重復(fù)使用它。模塊級別的函數(shù)會將最近編譯過的模式緩存起來,因此并不會消耗太多的性能,但是如果使用預(yù)編譯模式的話,你將會減少查找和一些額外的處理損耗。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: