在使用正則搜索內容時遇到一個小坑,百度搜了一下,遇到這個坑的還不少,特此記錄一下。
比如說有一個字符串 "123@qq.comaaa@163.combbb@126.comasdf111@asdfcom"
想匹配出里面所有的郵箱地址,該怎么實現呢?
寫了個正則,測試一下:
>>> import re >>> s = "123@qq.comaaa@163.combbb@126.comasdf111@asdfcom" >>> pattern1 = "\w+@(qq|163|126)\.com" >>> m1 = re.search(pattern1,s) >>> m1.group() '123@qq.com'
可以看到,能夠正確搜索到第一個結果,正則寫得沒問題,如果我想得到所有結果,自然而然就想到了用findall()方法。來試試看:
>>> m2 = re.findall(pattern1,s) >>> m2 ['qq', '163', '126']
這時候估計很多人就覺得奇怪了,使用search方法能搜索到,說明正則寫得沒問題呀,為什么使用findall的時候結果是這個樣子的?為什么結果不是整個郵箱字符串?
查了資料才清楚一個概念,叫做捕獲分組。
簡單說,就是正則表示式里出現括號的時候,括號里的內容匹配到的部分是會被作為結果輸出的,而不是把整個正則表達式匹配到的內容作為結果輸出。
所以,就出現了上面的結果了。
那怎么得到想要的結果呢?在Python里,當一個分組的頭部出現"?:"時,表示這是一個非捕獲分組,意思就是它只是正常參與匹配過程,但不作為獨立的結果進行輸出。
那么按這個寫法來試試:
>>> pattern2 = "\w+@(?:qq|163|126)\.com" >>> m2 = re.findall(pattern2,s) >>> m2 ['123@qq.com', 'aaa@163.com', 'bbb@126.com']
取消了這個捕獲分組,那么就是把整個表達式作為一個結果輸出,這樣才是我們預期想要的效果。
這種情況在使用正則中的“或”匹配時是特別需要注意的,因為這時候通常會加括號,很多初學者很容易掉進這個坑,得到一個不知所謂的結果。
當然,捕獲分組這個功能本來是正常有用的,只是要用對了才行。
比如,同樣是剛才這個例子,如果只想要郵箱中的用戶名部分,該怎么寫正則表達式呢?
顯然就是把用戶名部分加括號作為一個捕獲分組就可以了。
>>> pattern3 = "(\w+)@(?:qq|163|126)\.com"
>>> m3 = re.findall(pattern3,s)
>>> m3
['123', 'aaa', 'bbb']
對於findall()函數,其幫助是這么說明的:
findall函數,就是說在正則匹配里,如果有分組,就僅僅匹配分組里面的內容,然后返回這個組的列表; 如果有多個分組,那就把每一個分組看成一個單位,組合為一個元組,然后返回一個含有多個元組的列表。
分組這個功能還是比較強大的,以后會繼續學習更多的部分。
參考文章:https://blog.csdn.net/qq_42739440/article/details/81117919