Python實用技法第23篇:正則:文本模式的匹配和查找

上一篇文章: Python實用技法第22篇:利用Shell通配符作字符串匹配
下一篇文章: Python實用技法第24篇:正則:查找和替換文本

一、需求🙀

咱們想要按照特定的文本模式進行匹配或查找。

二、解決方案😸

若是想要匹配的只是簡單的文字,那麼一般只須要用基本的字符串方法就能夠了,好比str.find()、str.endswith()、str.startswith()或相似函數。正則表達式

示例:segmentfault

text='mark ,帥哥,18,183 帥,mark'
print(text=='mark')
print(text.startswith('mark'))
print(text.startswith('mark'))
print(text.find('帥哥'))

結果:緩存

False
True
True
6

若是更爲複雜的匹配則須要使用正則表達式以及re模塊。爲了說明使用正則表達式的基本流程,假設咱們想匹配以數字形式構成的日期,好比"11/27/2018"。示例以下:函數

import re
text1='11/27/2018'
text2='Nov 27, 2018'
if re.match(r'\d+/\d+/\d+',text1):
    print('符合模型:數字/數字/數字')
else:
    print('不符合模型:數字/數字/數字')

if re.match(r'\d+/\d+/\d+',text2):
    print('符合模型:數字/數字/數字')
else:
    print('不符合模型:數字/數字/數字')

運行結果:spa

符合模型:數字/數字/數字
不符合模型:數字/數字/數字

若是打算針對同一模型作屢次匹配,那麼一般會先將正則表達式模式預編譯成一個模式對象。code

例如:orm

import re
text1='11/27/2018'
text2='Nov 27, 2018'
datepat=re.compile(r'\d+/\d+/\d+')
if datepat.match(text1):
    print('符合模型:數字/數字/數字')
else:
    print('不符合模型:數字/數字/數字')

if datepat.match(text2):
    print('符合模型:數字/數字/數字')
else:
    print('不符合模型:數字/數字/數字')

結果:對象

符合模型:數字/數字/數字
不符合模型:數字/數字/數字

match()方法老是嘗試在字符串的開頭找到匹配項。若是想針對整個文本搜索出全部的匹配項,那麼就應該使用findall()方法,例如:字符串

import re
text='今天是 11/27/2018,昨天是11/26/2018'
datepat=re.compile(r'\d+/\d+/\d+')
print(datepat.findall(text))

運行結果:get

['11/27/2018', '11/26/2018']

當定義正則表達式時,咱們常會將部分模式用括號包起來的方式引入捕獲組,捕獲組一般簡化後續對匹配文本的處理,由於每一個組的內容均可以單獨提取出來。findall()方法搜索整個文本並找出全部的匹配項而後將它們以列表的形式返回。若是想以迭代的方式找出匹配項,可使用finditer()方法。

例如:

import re
#加入捕獲組
datepat=re.compile(r'(\d+)+/(\d+)+/(\d+)')
m=datepat.match('11/27/2018')
print(m.group(0))
print(m.group(1))
print(m.group(2))
print(m.group(3))
print(m.groups())
month,day,year=m.groups()
print(month)
print(day)
print(year)

print('*'*20)

text='今天是 11/27/2018,昨天是11/26/2018'
for month,day,year in datepat.findall(text):
    print('{}-{}-{}'.format(year,month,day))

print('*'*20)

for m in datepat.finditer(text):
    print(m.groups())

結果:

11/27/2018
11
27
2018
('11', '27', '2018')
11
27
2018
********************
2018-11-27
2018-11-26
********************
('11', '27', '2018')
('11', '26', '2018')

三、分析😈

本節主要介紹了re模塊對文本匹配和搜索的基本功能,首先用re.compile()對模式進行編譯,而後使用想match()、findall()、finditer()這樣的方法作匹配和搜索。

當指定模式時咱們一般會使用原始字符串,例如:

r'(\d+)/(\d+)/(\d+)'

這樣的字符串不會對反斜字符轉義,這在正則表達式中很是有用。不然,咱們須要用雙反斜槓線來標識一個單獨的'',例如:

'(\\d+)/(\\d+)/(\\d+)'

請注意match()方法只會檢查字符的開頭,有可能出現的匹配的結果並非你想要的,例如:

import re
#加入捕獲組
datepat=re.compile(r'(\d+)+/(\d+)+/(\d+)')
m=datepat.match('11/27/2018xxxx')
print(m)

結果:

<re.Match object; span=(0, 10), match='11/27/2018'>

若是想要精確匹配,能夠加一個結束標記:$

import re
#加入捕獲組
datepat=re.compile(r'(\d+)+/(\d+)+/(\d+)$')
m1=datepat.match('11/27/2018xxxx')
m2=datepat.match('11/27/2018')
print(m1)
print(m2)

結果:

None
<re.Match object; span=(0, 10), match='11/27/2018'>

若是隻是執行簡單的文本匹配和搜索操做,能夠省略編譯步驟。

若是打算執行不少匹配或查找操做的話,一般須要先將模式編譯而後重複使用。模塊級的函數會對最近編譯過的模式作緩存處理,而且比較省步驟。

上一篇文章: Python實用技法第22篇:利用Shell通配符作字符串匹配
下一篇文章: Python實用技法第24篇:正則:查找和替換文本
相關文章
相關標籤/搜索