正則匹配通俗地來說就是按照模板從給定的字符串裏找出想要的內容(按圖索驥,看圖找蛤蟆),這個模板即爲正則表達式。
python的正則表達式功能需要調用re模塊,re模塊中提供了不少有用的函數,比如:compile函數、match函數、search函數、findall函數、finditer函數、split函數、sub函數、subn函數等
目錄
一、正則函數
1. re.match函數
功能:re.match嘗試從字符串的起始位置匹配一個模式,如果匹配成功則返回一個匹配的對象,如果不是起始位置匹配成功的話,match()就返回none。
語法:re.match(pattern,string,flags=0)
2. re.search函數
功能:re.search 掃描整個字符串並返回第一個成功的匹配,如果匹配成功re.search方法返回一個匹配的對象,否則返回None。
語法:re.search(pattern, string, flags=0)
3. re.sub函數
功能:re.sub用於替換字符串中的匹配項。
語法:re.sub(pattern, repl, string, count=0, flags=0)
repl參數可以爲替換的字符串,也可以爲一個函數。
-
如果repl是字符串,那麼就會去替換字符串匹配的子串,返回替換後的字符串;
-
如果repl是函數,定義的函數只能有一個參數(匹配的對象),並返回替換後的字符串。
例子:
count可指定替換次數,不指定時全部替換。例如:
repl可以爲一個函數。例如:
4. re.subn函數
功能:和sub函數差不多,但是返回結果不同,返回一個元組“(新字符串,替換次數)”
例子:
5. re.compile函數
功能:compile 函數用於編譯正則表達式,生成一個正則表達式( Pattern )對象,供 match() 和 search() 這兩個函數使用。如果匹配成功則返回一個Match對象。
語法:re.compile(pattern[, flags])
注:compilte函數調用情況比較複雜,下面會有一節專門講解。
6. findall函數
功能:在字符串中找到正則表達式所匹配的所有子串,並返回一個列表,如果沒有找到匹配的,則返回空列表。
語法:findall(string[, pos[, endpos]])
例子:
7. re.finditer函數
功能:在字符串中找到正則表達式所匹配的所有子串,並把它們作爲一個迭代器返回。
語法:re.finditer(pattern, string, flags=0)
8. re.split函數
功能:split 方法用pattern做分隔符切分字符串,分割後返回列表。如果用'(pattern)',那麼分隔符也會返回。
語法:re.split(pattern, string[, maxsplit=0, flags=0])
例子:
小結:
1. 函數辨析:match和search的區別
re.match只匹配字符串的開始,如果字符串開始不符合正則表達式,則匹配失敗,函數返回None;
re.search匹配整個字符串,直到找到一個匹配。
2. 函數辨析:3個匹配函數match、search、findall
match 和 search 只匹配一次 ,匹配不到返回None,findall 查找所有匹配結果。
3. 函數返回值
函數re.finditer 、 re.match和re.search 返回匹配對象,而findall、split返回列表。
二、re模塊調用
re模塊的使用一般有兩種方式:
方法1:
直接使用上面介紹的 re.match, re.search 和 re.findall 等函數對文本進行匹配查找。
方法2:
(1)使用compile 函數將正則表達式的字符串形式編譯爲一個 Pattern 對象;
(2)通過 Pattern 對象提供的一系列方法對文本進行匹配查找,獲得匹配結果(一個 Match 對象);
(3)最後使用 Match 對象提供的屬性和方法獲得信息,根據需要進行其他的操作。
接下來重點介紹一下compile函數。
re.compile函數用於編譯正則表達式,生成一個Pattern對象,調用形式如下:
re.compile(pattern[, flag])
其中,pattern是一個字符串形式的正則表達式,flag是一個可選參數(下一節具體講解)。
例子:
1. match函數
使用語法:
(1)re.match(pattern, string[, flags])
這個之前講解過了。
(2)Pattern對象:match(string[, pos[, endpos]])
其中,string 是待匹配的字符串,pos 和 endpos 是可選參數,指定字符串的起始和終點位置,默認值分別是 0 和 len (字符串長度)。因此,當不指定 pos 和 endpos 時,match 方法默認匹配字符串的頭部。當匹配成功時,返回一個 Match 對象,如果沒有匹配上,則返回 None。
例子:
當匹配成功時會返回一個Match對象,其中:
-
group([0, 1, 2,...]): 可返回一個或多個分組匹配的字符串,若要返回匹配的全部字符串,可以使用group()或group(0)。
-
start(): 匹配的開始位置。
-
end(): 匹配的結束位置。
-
span(): 包含起始、結束位置的元組。等價於(start(), end())。
-
groups(): 返回分組信息。等價於(m.group(1), m.group(2))。
-
groupdict(): 返回命名分組信息。
例子:
2. search函數
使用語法:
(1)re.search(pattern, string, flags=0)
這個函數前面已經講解過了。
(2)Pattern對象:search(string[, pos[, endpos]])
例子:
3. findall函數
使用語法:
(1)findall(string[, pos[, endpos]])
這個函數前面已經講解過了。
(2)Pattern對象:findall(string[, pos[, endpos]])
findall 以列表形式返回全部能匹配的子串,如果沒有匹配,則返回一個空列表。
例子:
4. finditer函數
使用語法:
(1)re.finditer(pattern, string, flags=0)
這個函數前面已經講解過了。
(2)Pattern對象:finditer(string[, pos[, endpos]])
finditer 函數與 findall 類似,但是它返回每一個匹配結果(Match 對象)的迭代器。
例子:
5. split函數
使用語法:
(1)re.split(pattern, string[, maxsplit=0, flags=0])
這個函數前面已經講解過了。
(2)Pattern對象:split(string[, maxsplit]])
maxsplit 可指定分割次數,不指定將對字符串全部分割。
例子:
6. sub函數
使用語法:
(1)re.sub(pattern, repl, string, count=0, flags=0)
這個函數前面已經講解過了。
(2)Pattern對象:sub(repl, string[, count])
當repl爲字符串時,可以用\id的形式引用分組,但不能使用編號0;當repl爲函數時,返回的字符串中不能再引用分組。
7. subn函數
subn和sub類似,也用於替換操作。使用語法如下:
Pattern對象:subn(repl, string[, count])
返回一個元組,元組第一個元素和sub函數的結果相同,元組第二個元素返回替換次數。
例子:
小結:
1. 使用Pattern對象的match、search、findall、finditer等函數可以指定匹配字符串的起始位置。
2. 對re模塊的兩種使用方式進行對比:
-
使用 re.compile 函數生成一個 Pattern 對象,然後使用 Pattern 對象的一系列方法對文本進行匹配查找;
-
直接使用 re.match, re.search 和 re.findall 等函數直接對文本匹配查找。
例子:
在上述例子中,我們發現他們共用了同一個正則表達式,表明上看好像沒發現什麼問題,但是當我們結合正則表達式的匹配過程進行分析時,就會發現這兩種調用方式的效率是不一樣的。使用正則表達式進行匹配的流程如下圖所示:
所以匹配流程是先對正則表達式進行編譯,然後得到一個對象,再使用該對象對需要匹配的文本進行匹配。這時我們就發現方式2會對正則表達式進行了多次編譯,這樣效率不就降低了嘛。
所以我們可以得到如下結論:
如果一個正則表達式要用多次,那麼出於效率考慮,我們可以預先編譯正則表達式,然後調用的一系列函數時複用。如果直接使用re.match、re.search等函數,則需要每一次都對正則表達式進行編譯,效率就會降低。因此在這種情況下推薦使用第一種方式
三、貪戀匹配
正則表達式匹配時默認的是貪戀匹配,也就是會盡可能多的匹配更多字符。如果想使用非貪戀匹配,可以在正則表達式中加上'?'。
實例:
四、分組
如果你想要提取子串或是想要重複提取多個字符,那麼你可以選擇用定義分組的形式。用()就可以表示要提取的分組(group),接下來用幾個實例來理解一下分組的使用方式:
例子1:
正則表達式'(\d{4})-(\d{3, 8})$'表示匹配兩個分組,第一個分組(\d{4})是一個有4個數字的子串,第二個分組(\d{3,8})表示匹配一個數字子串,子串長度爲3到8之間。
例子2:
正則表達式'(\d{1,3}\.){3}\d{1,3}‘的匹配過程分爲兩個部分,'(\d{1,3}\.){3}'表示匹配一個長度爲1到3之間的數字子串加上一個英文句號的字符串,重複匹配 3 次該字符串,'\d{1,3}'表示匹配一個1到3位的數字子串,所以最後得到結果123.456.78.90。
例子3:
(.*)第一個分組,.* 代表匹配除換行符之外的所有字符。(.*?) 第二個匹配分組,.*? 後面加了個問號,代表非貪婪模式,只匹配符合條件的最少字符。後面的一個 .* 沒有括號包圍,所以不是分組,匹配效果和第一個一樣,但是不計入匹配結果中。
group() 等同於group(0),表示匹配到的完整文本字符;
group(1) 得到第一組匹配結果,也就是(.*)匹配到的;
group(2) 得到第二組匹配結果,也就是(.*?)匹配到的;
因爲只有匹配結果中只有兩組,所以如果填 3 時會報錯。
擴展:其他組操作如:命名組的使用、定義無捕獲組、使用反向引用等,這部分內容還未弄懂,想了解的同學可以查看以下鏈接http://wiki.jikexueyuan.com/project/the-python-study-notes-second-edition/string.html
五、正則表達式修飾符
正則表達式可以包含一些可選標誌修飾符來控制匹配的模式。
修飾符被指定爲一個可選的標誌。多個標誌可以通過按位 OR(|) 它們來指定。
例子:
六、正則表達式模式
七、常見的正則表達式
通常情況下,通過實例學習是一個高效的途徑。接下來我將整理一些常見的正則表達式應用實例,大家可以試着將前面學的理論知識應用於實踐啦。
(1)匹配國內13、15、18開頭的手機號碼的正則表達式
(2)匹配中文的正則表達式
中文的unicode編碼範圍主要在 [\u4e00-\u9fa5]
,這個範圍之中不包括全角(中文)標點。當我們想要把文本中的中文漢字提取出來時可以使用如下方式:
(3)匹配由數字、26個英文字母或下劃線組成的字符串的正則表達式
(4)匹配金額,精確到 2 位小數
(5)提取文本中的URL鏈接
(6)匹配身份證號碼
(7)匹配整數
更多正則的相關內容可以參考以下文章:
極客學院的學習筆記:
1. python之旅 http://wiki.jikexueyuan.com/project/explore-python/Regular-Expressions/README.html
2. python網絡爬蟲 http://wiki.jikexueyuan.com/project/python-crawler/regular-expression.html
3. 輕鬆學習正則表達式 http://wiki.jikexueyuan.com/project/regex/introduction.html
4. python正則表達式指南
http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html
5.附一在線正則調試網址:https://rubular.com/
最後,推薦一個更強大的正則表達式引擎-python的regex模塊