什麼是正則? 正則表達式也稱為正則,是一個特殊的字元序列,能幫助檢查一個字元串是否與某種模式匹配。可以用來進行驗證:郵箱、手機號、qq號、密碼、url = 網站地址、ip等。正則不是python語言獨有的技術,python語言直到1.5版本才將正則表達式完成的整理/納入進re模塊中,我們只需要導入r ...
什麼是正則?
正則表達式也稱為正則,是一個特殊的字元序列,能幫助檢查一個字元串是否與某種模式匹配。可以用來進行驗證:郵箱、手機號、qq號、密碼、url = 網站地址、ip等。正則不是python語言獨有的技術,python語言直到1.5版本才將正則表達式完成的整理/納入進re模塊中,我們只需要導入re模塊,然後就可以使用其中所有和正則相關的函數和屬性了。
1. re模塊中最常用的幾個函數
1). re.match函數:
功能:將string數據從頭開始嘗試匹配 ;如果匹配成功,那麼就會返回給程式一個match對象;如果開頭就不匹配,那麼直接返回None值;
語法格式:re.match(regex, string[, flags=0])
參數:regex:匹配的正則表達式(內部定義了一套驗證規則)
string:需要被驗證的字元串數據
flags:可選參,模式/標誌位,用於控制正則表達式的匹配方式,如:是否區分大小寫,多行匹配等等。預設情況下(不顯示定義) --> 不開啟任何的模式
【註意】匹配成功re.match方法返回一個匹配的對象,否則返回None。我們可以使用group(num) 或 groups() 等匹配對象函數來獲取匹配表達式。match對象有5個常用的函數:
(1). group():返回匹配成功的數據值(理解:原串中的某部分子串信息)
(2). start():返回匹配成功的數據的起始索引
(3). end(): 返回匹配成功的數據的結束索引
(4). span(): 返回一個元祖對象,有兩個元素組成;第一個元素記錄了匹配成功的數據的起始索引第二個元素記錄了匹配成功的數據的結束索引
(5). groups():以元祖的形式返回所有子組的信息(一個包含所有小組字元串的元組,從1到所含的小組號);如果沒有進行正則分組,則返回一個空元祖。
1 import re
2
3 mo = re.match(r'Www','www.baidu.com') 4 print(mo) # None 5 print(type(mo)) # <class 'NoneType'> 6 7 print(re.match(r'www','www.sina.com')) # <_sre.SRE_Match object; span=(0, 3), match='www'> 8 print(re.match(r'www','www.sina.com').group()) # www 9 print(re.match(r'www','www.sina.com').start()) # 0 10 print(re.match(r'www','www.sina.com').end()) # 3 11 print(re.match(r'www','www.sina.com').span()) # (0,3) 12 print(re.match(r'www','www.sina.com').groups()) # () 13 print(re.match(r'WWW','www.sina.com')) # None 14 print(re.match(r'WWW','www.sina.com',flags=re.I)) # <_sre.SRE_Match object; span=(0, 3), match='www'> 15 16 17 18 line = "Cats are smarter than dogs" 19 20 matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I) 21 22 if matchObj: 23 print(matchObj.group()) # "Cats are smarter than dogs" 24 print(matchObj.group(1)) # "Cats" 25 print(matchObj.group(2)) # "smarter"
26 print(matchObj.groups()) # ("Cats","smarter")
27 else:
28 print("No match!!")
【補充】:第二種方式實現正則對數據的校驗:re.compile函數
功能:compile 函數用於編譯正則表達式,生成一個正則表達式( Pattern )對象,供 match() 和 search() 這兩個函數使用。
語法格式為:re.compile(regex[, flags])
參數:和match一樣理解
【註意】compile 函數執行完畢以後返回給程式一個Pattern對象(理解:對象的內部封裝了一套regex和flags),可以再通過Pattern對象調用其match函數(此時的match函數只需要傳遞一個參數:string即可)
compile()配合match()使用演示:
1 import re 2 3 pat = re.compile(r'www',flags=re.I) 4 print(pat) # re.compile('www', re.IGNORECASE) 5 print(type(pat))) # <class '_sre.SRE_Pattern'> 6 print(pat.match('www.baidu.com')) # <_sre.SRE_Match object; span=(0, 3), match='www'> 7 8 # 相當於 re.compile.match(r'www','www.baidu.com',flags=re.I)
【註意事項】:
1).正則表達式返回的索引值需要滿足含頭不含尾的特點
2).正則表達式驗證的數據內容嚴格區分大小寫
3).之後在定義正則表達式的時候,在它的第一個引號前面,都顯示的追加一個r,無腦行為...(轉義字元)
2). re.search函數:
功能:從頭開始嘗試匹配,如果開頭就匹配不成功,不會返回None值,會繼續嘗試往後匹配;一旦匹配成功了,就直接返回一個match對象,後續就算還存在可以匹配成功的子串數據,也不會再匹配了(直接無視);如果直到最後都匹配不成功,返回一個None值。
語法格式:re.search(regex,string[,flags=0])
參數:和match一樣理解
【補充】:由於search函數調用返回的是match對象,所以仍然可以調用5個常用的函數
1 import re 2 3 print(re.match(r'www','hahawww.baidu.com!!www.qfedu.comhehe')) # None 4 print(re.search(r'www','hahawww.baidu.com!!www.qfedu.comhehe')) # <_sre.SRE_Match object; span=(4, 7), match='www'> 5 print(re.search(r'www','hahawww.baidu.com!!www.qfedu.comhehe').group()) # www 6 print(re.search(r'www','hahawww.baidu.com!!www.qfedu.comhehe').start()) # 4 7 print(re.search(r'www','hahawww.baidu.com!!www.qfedu.comhehe').end()) # 7 8 print(re.search(r'www','hahawww.baidu.com!!www.qfedu.comhehe').span()) # (4, 7) 9 print(re.search(r'www','hahawww.baidu.com!!www.qfedu.comhehe').groups()) # () 10 print(re.search(r'Www','hahawww.baidu.com!!www.qfedu.comhehe')) # None 11 print(re.search(r'Www','hahawww.baidu.com!!www.qfedu.comhehe',flags=re.I)) # <_sre.SRE_Match object; span=(4, 7), match='www'>
compile()配合search()使用演示:
1 import re 2 3 pat = re.compile(r'www') 4 mo = pat.search('Wwww.sina.com!!www.baidu.com!!www') 5 6 print(mo) # <_sre.SRE_Match object; span=(1, 4), match='www'>
3). re.findall函數:
功能:在字元串中找到所有匹配成功的子數據(子串),都存入到列表中返回;如果一個都匹配不成功,那麼返回一個空列表。
語法格式:re.findall(regex,string[, pos[, endpos]][,flags=0])
參數:pos:可選參數,指定字元串的起始位置,預設為 0
endpos :可選參數,指定字元串的結束位置,預設為字元串的長度
其他參數和match、search一樣理解
1 import re 2 3 lt = re.findall(r'www','www.sina.com!!www.baidu.com') 4 print(lt,type(lt)) # ['www', 'www'] <class 'list'> 5 6 lt1 = re.findall(r'WWW','www.sina.com!!www.baidu.com!!WWW',flags=re.I) 7 print(lt1,type(lt1)) # ['www', 'www', 'WWW'] <class 'list'> 8
compile()配合search()使用演示:
1 import re 2 3 pat = re.compile(r'www',flags=re.I) 4 lt = pat.findall('www.sina.com!!www.baidu.com!!WWW') 5 6 print(lt) # ['www', 'www', 'WWW'] 7 8 9 10 pattern = re.compile(r'\d+') # 查找數字 11 result1 = pattern.findall('runoob 123 google 456') # 不指定字元串的起始和結束位置 12 result2 = pattern.findall('run88oob123google456', 0, 10) # 指定字元串的起始和結束位置 13 14 print(result1) # ['123', '456'] 15 print(result2) # ['88', '12']
4). re.finditer函數:
功能:和 findall 類似,在字元串中找到正則表達式所匹配的所有子串,但是將所有匹配成功的數據封裝為一個一個的match對象, 然後以iterator(迭代器對象)返回
語法格式:finditer(regex,string[,flags=0])
參數:和match、search、findall一樣理解
1 import re 2 3 it = re.finditer('apple', 'i hate apple apple apple so much') 4 5 # iterator(迭代器對象)不能直接使用內置函數len()執行查看其容量大小,會報錯:TypeError; 但是可以先將其轉換為容器對象(list、tuple...),就可以被len()所執行了; 6 print(len(it)) # TypeError 7 print(len(list(it))) # 3 8 9 # 使用遍歷的思想去訪問iterator中的元素 10 for i in it: 11 print(i) 12 print(type(i)) 13 print(i.group()) 14 15 # <_sre.SRE_Match object; span=(7, 12), match='japan'> 16 # <class '_sre.SRE_Match'> 17 # apple 18 19 # <_sre.SRE_Match object; span=(13, 18), match='japan'> 20 # <class '_sre.SRE_Match'> 21 # apple 22 23 # <_sre.SRE_Match object; span=(19, 24), match='japan'> 24 # <class '_sre.SRE_Match'> 25 # apple 26 27 #迭代器對象中的內容只能被使用一次,不可逆,否則報錯:StopIteration 28 # print(next(it)) 29 30 # 使用while迴圈來遍歷iterator對象,結果和for......in..一樣 31 while 1: 32 try: 33 mo = next(it) 34 print(mo) 35 print(mo.group()) 36 except: 37 break
5). re.sub 函數:
功能:替換字元數據
語法格式:sub(regex,repl,string,[count],[flags=0]):返回字元串(已經被替換完成後的內容)
subn(regex,repl,string,[count],[flags=0]):返回元祖對象,此對象有兩個元素;第一個元素記錄了替換以後的字元串內容,第二個元素記錄了被替換的次數(count)
參數:regex:正則規則(字元串)
repl:替換成的字元串內容,也可為一個函數
string:原串數據
count:次數,模式匹配後替換的最大次數,預設 為0 表示替換所有的匹配
1 import re 2 3 str1 = re.sub('beijing', 'shanghai', 'i love beijing beijing beijing so much') 4 print(str1,type(str1)) # i love shanghai shanghai shanghai so much <class 'str'> 5 6 tp = re.subn('beijing', 'shanghai', 'i love beijing beijing beijing so much', 2) # 2改成4也不會報錯,就會全部替換 7 print(tp,type(tp)) # ('i love shanghai shanghai beijing so much', 2) <class 'tuple'> 8 9 10 # 示例:模擬讓游戲世界變得和諧(使用正則) 11 regex = r'CNM|MB|SB|NC|WQNMLGB|TMD|NND' 12 game = 'WQNMLGB!!連裝備都不會出...小學生!!SB...' 13 14 s = re.sub(regex,'***',game) 15 print(s) # ***!!連裝備都不會出...小學生!!***... 16 17 18 # 示例:刪除某些內容 19 phone = "2004-959-559 # 這是一個國外電話號碼" 20 21 # 刪除字元串中的Python註釋 22 num = re.sub(r'#.*$', "", phone) 23 print("電話號碼是: ", num) # 電話號碼是: 2004-959-559 24 25 # 刪除非數字(-)的字元串 26 num = re.sub(r'\D', "", phone) 27 print("電話號碼是 : ", num) # 電話號碼是 : 2004959559 28 29 30 # 示例:repl參數是一個函數時,將字元串中的匹配的數字乘以 2 31 # 將匹配的數字乘以 2 32 def double(matched): 33 value = int(matched.group('value')) 34 return str(value * 2) 35 36 s = 'A23G4HFD567' 37 print(re.sub('(?P<value>\d+)', double, s)) # A46G8HFD1134
【補充示例】:替換相關的操作
1 str5 = 'dsaf######32141asf#####dsafa#########()!,.___######21341##' 2 3 # 將一個#替換成為一個- 4 regex1 = r'#' 5 str6 = re.sub(regex1,'-',str5) 6 print(str6) # dsaf------32141asf-----dsafa---------()!,.___------21341-- 7 8 # 將一堆#替換成為一個- 9 regex2 = r'#+' 10 tp = re.subn(regex2,'-',str5) 11 print(tp) # ('dsaf-32141asf-dsafa-()!,.___-21341-', 5)
6). re.split 函數:
功能:按照能夠匹配的子串將字元串分割後返回列表
語法格式:re.split(regex, string[, maxsplit=0, flags=0])
參數:maxsplit :分隔次數,maxsplit=1 分隔一次,預設為 0,不限制次數
1 import re 2 3 str1 = 'i love shanghai so much' 4 regex = r' +' # 切割空格,+表示一個到多個,有貪婪行為,把空格全切了 5 lt = re.split(regex,str1) 6 print(lt) # ['i', 'love', 'shanghai', 'so', 'much'] 7 8 str2 = 'i love shanghai so much' 9 regex = r' +?' # 切割空格 +表示一個到多個, ?取消貪婪行為,能少切就少切 10 lt = re.split(regex,str2) 11 print(lt) # ['i', '', '', '', '', '', '', 'love', '', '', '', '', '', '', '', 'shanghai', '', '', '', 'so', '', 'much'] 12 13 str3 = 'dasfas23141sfa123dsafas13dasdfa1231241____3241234^&*&(dsafa 14 214331asdfa' 15 regex = r'\d+?' 16 lt = re.split(regex,str3) 17 print(lt) # ['dasfas', '', '', '', '', 'sfa', '', '', 'dsafas', '', 'dasdfa', '', '', '', '', '', '', '____', '', '', '', '', '', '', '^&*&(dsafa', '', '', '', '', '', 'asdfa'] 18 19 regex1 = r'\d+' 20 lt1 = re.split(regex1,str3) 21 print(lt1) # ['dasfas', 'sfa', 'dsafas', 'dasdfa', '____', '^&*&(dsafa', 'asdfa']
2. 正則表達式修飾符 - 可選標誌(flags)
正則表達式可以包含一些可選標誌修飾符來控制匹配的模式。修飾符被指定為一個可選的標誌。多個標誌可以通過按位 OR(|) 它們來指定。如 re.I | re.M 被設置成 I 和 M 標誌:
re.I:使匹配對大小寫不敏感,忽略大小寫
re.L:做本地化識別(locale-aware)匹配,表示特殊字元集 \w, \W, \b, \B, \s, \S 依賴於當前環境
re.M:多行匹配,影響 ^ 和 $,多行模式
re.S:使.匹配包括換行在內的所有字元
re.U:根據Unicode字元集解析字元。這個標誌影響 \w, \W, \b, \B
re.X:該標誌通過給予你更靈活的格式以便你將正則表達式寫得更易於理解,即為了增加可讀性,忽略空格和 # 後面的註釋
3. 正則中元字元的使用
正則表達式模式:模式字元串使用特殊的語法來表示一個正則表達式:字母和數字表示他們自身。一個正則表達式模式中的字母和數字匹配同樣的字元串。多數字母和數字前加一個反斜杠時會擁有不同的含義。標點符號只有被轉義時才匹配自身,否則它們表示特殊的含義。反斜杠本身需要使用反斜杠轉義。由於正則表達式通常都包含反斜杠,所以你最好使用原始字元串來表示它們。模式元素(如 r'\t',等價於 '\\t')匹配相應的特殊字元。下表列出了正則表達式模式語法中的特殊元素。如果你使用模式的同時提供了可選的標誌參數,某些模式元素的含義會改變。
匹配單個字元(數字、英文、其它...)符號位:
[ ]:表示一字元位
[9876123450]:表示一位,取值範圍:[0,9]中間的任何一位值
[0-9]:表示一位,取值範圍:[0,9]中間的任何一位值
\d:表示一位,取值範圍:[0,9]中間的任何一位值
\D:對以上的\d進行取反,意味著:匹配除了數字字元以外的所有字元
[24680]:表示一位,取值範圍:2、4、6、8、0中的任何一個值
[abcdefg]:表示一位,取值範圍:a、b、c、d、e、f、g中的任何一個值
[a-z]:表示一位,取值範圍:[a,z]中的任何一個值
[A-Z]:表示一位,取值範圍:[A,Z]中的任何一個值
[0-9a-zA-Z_]:表示一位,取值範圍:0~9、a~z、A~Z以及_中的任何一個值
\w:表示一位,取值範圍:0~9、a~z、A~Z以及_中的任何一個值
\W:對\w進行取反操作,意味著:匹配除了0~9、a~z、A~Z以及_中的其它所有字元
.: 匹配除了換行符以外的所有字元
匹配錨字元(邊界字元):
^:從字元串數據的頭部開始匹配,在開啟了多行模式的情況下(re.M),它可以嘗試匹配每一行的頭部數據
$:從字元串數據的尾部開始匹配,在開啟了多行模式的情況下(re.M),它可以嘗試匹配每一行的尾部數據
\A:從字元串數據的頭部開始匹配,在開啟了多行模式的情況下(re.M),它沒有多行的概念,還是匹配第一行的頭部數據
\Z:從字元串數據的尾部開始匹配,在開啟了多行模式的情況下(re.M),它沒有多行的概念,還是匹配最後一行的尾部數據
補充:
\b:嘗試匹配邊界(左側、右側)數據,如果一旦滿足返回對象(match、list)
\B:先捨棄規定邊界的數據,然後一定滿足從左側開始匹配數據,...
匹配多個字元:
以下的一些x,y,n等都是變數名
1).模糊匹配: