re 模塊爲Python的內置模塊,Python程序中經過這個模塊來使用正則表達式。python
re 模塊有兩種使用方式,示例中以match方法爲例。正則表達式
方式 1:c#
步驟: 1)直接使用 re.match 方法(傳入正則表達式和須要匹配的字符串)對文本進行匹配查找,match方法返回一個 Match 對象 2)使用 Match 對象提供的方法獲取匹配結果
示例:ide
import re m = re.match(r'\d+', '123abc456') # 返回一個 Match 對象 print(m.group()) # 輸出匹配結果:123
方式 2:spa
步驟: 1)使用 re.compile 方法(傳入正則表達式)獲得 Pattern 對象 2)經過 Pattern 對象提供的方法對字符串進行匹配查找,返回一個 Match 對象(包含了匹配結果) 3)使用 Match 對象提供的方法獲取匹配結果
示例:翻譯
import re pattern = re.compile(r'\d+') # 返回一個 Pattern 對象 m = pattern.match('123abc456') # 返回一個 Match 對象 print(m.group()) # 輸出匹配結果:123
如上2種方式的區別在於,第二種方式經過 re.compile 方法獲取一個 Pattern 對象,使得一個正則表達式被屢次用於匹配;而第一種方式,每一次的匹配都須要傳入正則表達式。3d
re.compile(pattern[, flag])
示例中的 compile 方法用於編譯正則表達式,返回一個 Pattern 對象,可利用 Pattern 對象中的一系列方法對字符串進行匹配查找。Pattern 對象中的經常使用方法包括:match,search,findall,finditer,split,sub,subn。固然這些方法也可使用 re模塊直接調用~code
match 方法用於從字符串的頭部開始匹配,僅返回第一個匹配的結果~對象
pattern.match(string[, pos[, endpos]]) 或 re.match(pattern, string[, flags])
pattern.match(string[, pos[, endpos]]) 中的 pos,endpos指定字符串匹配的起始和終止位置,這兩個均爲可選參數,若不指定,默認從字符串的開頭開始匹配~
re.match(pattern, string[, flags]) 中的pattern爲傳入的正則表達式,flags指定匹配模式,如忽略大小寫,多行模式,同compile方法中的flag參數~
blog
能夠經過在正則表達式中使用小括號'()',來對匹配到的數據進行分組,而後經過group([n]),groups()獲取對應的分組數據。
import re pattern = re.compile('([0-9]*)([a-z]*)([0-9]*)') m = pattern.match('123abc456') # 輸出匹配的完整字符串 print(m.group()) # 123abc456 # 同上,輸出匹配的完整字符串 print(m.group(0)) # 123abc456 # 從匹配的字符串中獲取第一個分組 print(m.group(1)) # 123 # 從匹配的字符串中獲取第二個分組 print(m.group(2)) # abc # 從匹配的字符串中獲取第三個分組 print(m.group(3)) # 456 # 從匹配的字符串中獲取全部分組,返回爲元組 print(m.groups()) # ('123', 'abc', '456') # 獲取第二個分組 在字符串中的起始位置(分組第一個字符的索引),start方法的默認參數爲0,即字符串的起始索引 print(m.start(2)) # 3 # 獲取第二個分組 在字符串中的起始位置(分組最後一個字符的索引+1),通start方法,end方法的默認參數也爲0,即字符串結尾的索引+1 print(m.end(2)) # 6 # 第三個分組的起始和結束位置,即 (start(3), end(3)) print(m.span(3)) # (6, 9) # 同 (start(), end()) print(m.span()) # (0, 9)
上述中的 group(),groups(),start(),end(),span() 方法均爲 Match類中的方法,這些方法主要用於從匹配的字符串中(或者說是從 Match對象中)獲取相關信息~
re 模塊中較爲經常使用的方法除了 compile() 和 match() 方法,還有下面列出的這些~
不一樣於match方法的從頭開始匹配,search方法用於在字符串中的進行查找(從左向右進行查找),只要找到一個匹配結果,就返回 Match 對象,若沒有則返回None~
search(string[, pos[, endpos]]) # 可選參數 pos,endpos 用於指定查找的起始位置和結束位置,默認 pos 爲0,endpos爲字符串長度
示例:re.search
import re pattern = re.compile(r'[a-z]+') m = pattern.match('123abc456cde') print(m) # None m = pattern.search('123abc456cde') # 或者 m = re.search(r'[a-z]+', '123abc456') print(m.group()) # abc
因爲match是從頭開始匹配,因此這裏匹配不到結果~
match方法 和search方法 僅會返回一個結果,findall方法會將字符串中的全部匹配結果以列表的形式返回,注意,返回的是列表,不是 Match 對象~
findall(string[, pos[, endpos]]) # 可選參數 pos,endpos 用於指定查找的起始位置和結束位置,默認 pos 爲0,endpos爲字符串長度
示例:
import re pattern = re.compile(r'[a-z]+') res = pattern.findall('123abc456cde') print(res) # 執行結果: ['abc', 'cde']
findall方法的優先級查詢,findall方法會優先把匹配結果組裏的內容進行返回,來看以下示例:
import re pattern = re.compile('\d([a-z]+)\d') print(pattern.findall('123abc456')) # 輸出結果: ['abc']
其實咱們想要的結果是 '3abc4',可是findall方法會優先返回分組中的內容,即 'abc'。若要想要匹配結果,取消權限便可,就是在小括號的起始位置加上 '?:'
import re pattern = re.compile('\d(?:[a-z]+)\d') print(pattern.findall('123abc456')) # 輸出結果: ['3abc4']
finditer 方法與 findall方法相似,會查找整個字符串並返回全部匹配的結果,返回的是一個迭代器,且每個元素爲 Match 對象~
import re pattern = re.compile(r'\d+') res = pattern.finditer('#123abc456cde') for i in res: print(i.group()) # 輸出結果: 123 456
split方法用於將字符串進行切割,切割使用的分隔符就是字符串中被匹配到的子串,將被切割後的子串以列表的形式返回~
split(string[, maxsplit]) # maxsplit 參數用於指定最大分割次數,默認會將這個字符串分割
示例:
import re pattern = re.compile(r'\d+') m = pattern.split('abc23de3fgh3456ij') # 或者直接 re.split('\d+','abc23de3fgh3ij') print(m) # 結果輸出: ['abc', 'de', 'fgh', 'ij']
正則表達式中添加括號後,則會保留分隔符
import re ret = re.split("(\d+)", "abc23de3fgh3456ij") print(ret) # 結果輸出」 ['abc', '23', 'de', '3', 'fgh', '3456', 'ij']
sub方法用於將字符串中匹配的子串替換爲指定的字符串
pattern.sub(repl, string[, count]) 或者 re.sub(pattern, repl, string[, count])
count爲可選參數,指定最大替換次數,repl 能夠是一個字符串,也能夠是一個 \id 引用匹配到的分組(但不能使用 \0),還能夠是一個方法,該方法僅接受一個參數(Match對象),且返回一個字符串~
1)repl 是一個字符串
import re ret = re.sub(r'\d+', '###', 'abc123cde') print(ret) # 輸出結果: abc###cde
2)repl 是一個分組引用
將相似於 'hello world' 這樣的字符串先後兩個單詞替換~
import re ret = re.sub(r'(\w+) (\w+)', r'\2 \1', 'hello world; hello kitty') print(ret) # 輸出結果: world hello; kitty hello
3)repl是一個方法
import re def func(m): return 'hi' + ' ' + m.group(2) ret = re.sub(r'(\w+) (\w+)', func, 'hello world; hello kitty') print(ret) # 輸出結果: hi world; hi kitty
subn方法和sub方法相似,subn方法會返回一個元組,元組有兩個元素,第一個元素與sub方法返回的結果一致,第二個元素爲字符串中被替換的子串個數
import re def func(m): return 'hi' + ' ' + m.group(2) ret = re.subn(r'\d+', '###', 'abc123cde') print(ret) ret = re.subn(r'(\w+) (\w+)', r'\2 \1', 'hello world; hello kitty') print(ret) ret = re.subn(r'(\w+) (\w+)', func, 'hello world; hello kitty') print(ret) # 輸出結果: ('abc###cde', 1) ('world hello; kitty hello', 2) ('hi world; hi kitty', 2)
正則匹配默認使用的就是貪婪匹配,也就是儘量的多匹配,以下示例爲貪婪匹配:
import re m = re.match('[a-z]+', 'abc123def') print(m.group()) # 輸出結果: abc
同一示例使用非貪婪匹配,在正則後面加上一個 '?' 便可,注意這個問號不是表明0個或者一個(注意區分):
import re m = re.match('[a-z]+?', 'abc123def') print(m.group()) # 輸出結果: a
貪婪匹配(單單使用 ?),?重複0個或者1個,貪婪模式下匹配一個
ret=re.findall('13\d?','1312312312, 134, 34234, 2313') print(ret) # 輸出結果: ['131', '134', '13']
惰性匹配示例:
ret=re.findall('131\d+?','1312312312') print(ret) # 輸出結果: ['1312']
一、反斜槓後邊跟元字符去除特殊功能, 好比.
二、反斜槓後邊跟普通字符實現特殊功能, 好比\d
\d 匹配任何十進制數; 它至關於類 [0-9]。 \D 匹配任何非數字字符; 它至關於類 [^0-9]。 \s 匹配任何空白字符; 它至關於類 [ \t\n\r\f\v]。 \S 匹配任何非空白字符; 它至關於類 [^ \t\n\r\f\v]。 \w 匹配任何字母數字字符; 它至關於類 [a-zA-Z0-9_]。 \W 匹配任何非字母數字字符; 它至關於類 [^a-zA-Z0-9_] \b 匹配一個特殊字符邊界,好比空格 ,&,#等
讓咱們看一下 \b 的應用:
ret=re.findall(r'I\b','I am LIST') print(ret) # ['I']
Tip:
如上示例中 ret=re.findall(r'I\b','I am LIST') 使用的是 r'I\b' 而不能使用 'I\b' ,解釋以下:
Python程序在這裏的執行過程分爲2步:
第一步:python 解釋器讀取 'I\b' 字符串進行解析,解析完成後傳遞給 re 模塊 第二步:re 模塊 對接收到的字符串進行解析
在第一步中,'\b' 和 '\n' 相似,對於Python解釋器而言,有特殊的意義,Python解釋器針對 '\b' 和 '\n' 會根據ASCII碼錶進行翻譯,翻譯完成以後再傳遞給 re 模塊進行後續的處理;因此 re 模塊獲取到的不會是 原模原樣的 'I\b'。這裏若要讓 re 模塊接收到原模原樣的 'I\b',有兩種方式:
1)在字符串中使用 \ ,將 \b 轉義 re.findall('I\\b','I am LIST') 2)直接在字符串前面加 r,使字符串中的 \b 失效,建議使用這種方式 re.findall(r'I\b','I am LIST')
還有一種狀況,要匹配的字符串自己就包含 '\' , 例如匹配 'hello\kitty' 中的 'o\k'
分析:\ 對於re 模塊而言,有轉義的意思,因此 re 模塊但願獲取到的字符串規則是 'o\k',也就是說Python解釋器解析完字符串後傳遞給 re 模塊的是 'o\k'(若是直接使用 re.findall('o\k','hello\kitty') ,re模塊獲取到的是 'o\k'),因此這裏也有兩種實現方式:
1)re.findall(r'o\\k','hello\kitty') ,建議使用這種方式 2)針對2個 \ 分別進行轉義 re.findall('o\\\\k','hello\kitty')
也許這裏會有疑問,re.findall("1\d?", "123,12345235,124234,1,abc,13") ,爲什麼這裏的\d 能夠直接使用,那是由於 \d 在ASCII碼錶裏面沒有對應的字符串(Python解釋器對 \d 不會進行翻譯),因此能夠直接使用。ASCII碼錶中和 '\' 連用的特殊字符見下圖:
|表示 或者,使用 | 時通常須要和 括號配合使用,否則沒法區分 | 的左邊與右邊
import re ret = re.search('(ab)|\d','#@123abc') # 匹配 ab 或者 數字,search僅會返回第一個匹配到的 print(ret.group()) # 1
import re # [bc] 表示僅匹配 b 或者 c,以下示例中表示,匹配 abd 或者 acd ret = re.findall('a[bc]d','acd') print(ret) #['acd'] # [a-zA-Z] : 全部大小寫字母 # [a-zA-Z0-9] : 全部大小寫字母及數字 # [a-zA-Z0-9_] : 全部大小寫字母及數字,再加上一個下劃線 ret = re.findall('[a-z]','acd') # 匹配全部小寫字母 print(ret) #['a', 'c', 'd'] # 注意:元字符在 字符集[] 中沒有任何效果,這裏的 . 和 + 就是普通的符號,有效果的元字符包括:- ^ \ ret = re.findall('[.*+]','a.cd+') print(ret) #['.', '+'] # - 表示範圍符號 ret = re.findall('[1-9]','45dha3') # 匹配數字 1 至 9 print(ret) #['4', '5', '3'] # ^ 表示取反,即匹配 非a,非b的字符 ret = re.findall('[^ab]','45bdha3') print(ret) #['4', '5', 'd', 'h', '3'] # \ 爲轉義符 ret = re.findall('[\d]','45bdha3') print(ret) #['4', '5', '3']
.................^_^