什么是正則?
正則表達式也稱為正則,是一個特殊的字符序列,能幫助檢查一個字符串是否與某種模式匹配。可以用來進行驗證:郵箱、手機號、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以及_中的其它所有字符
.: 匹配除了換行符以外的所有字符
代碼演示:
1 import re 2 3 reg = r'[12345]' 4 print(re.match(reg,'4')) # <_sre.SRE_Match object; span=(0, 1), match='4'> 5 print(re.match(reg,'42')) # <_sre.SRE_Match object; span=(0, 1), match='4'> 6 print(re.match(reg,'842')) # None 7 8 reg = r'[0-9]' # 兩者作用一樣reg = r'\d' 9 print(re.match(reg,'842')) # <_sre.SRE_Match object; span=(0, 1), match='8'> 10 11 reg = r'\d\d' 12 print(re.match(reg,'842')) # <_sre.SRE_Match object; span=(0, 2), match='84'> 13 14 reg = r'\D\d' 15 print(re.match(reg,'a842')) # <_sre.SRE_Match object; span=(0, 2), match='a8'> 16 17 reg = r'\w\d[a-z][0-9]' # 一共要匹配四位數據 18 print(re.match(reg,'_6a842')) #<_sre.SRE_Match object; span=(0, 4), match='_6a8'> 19 print(re.findall(reg,'_6a842')) # ['_6a8'] 20 print(re.findall(reg,'_6a842c7')) # ['_6a8', '42c7'] 21 22 reg1 = r'.' 23 print(re.match(reg1,'_6a842')) # <_sre.SRE_Match object; span=(0, 1), match='_'> 24 25 reg2 = r'..' 26 print(re.match(reg2,'_6a842')) # <_sre.SRE_Match object; span=(0, 2), match='_6'> 27 print(re.match(reg2,'\n_6a842')) # None 28 print(re.search(reg2,'\n_6a842')) # <_sre.SRE_Match object; span=(1, 3), match='_6'> 29 print(re.findall(reg2,'\n_6a842')) # ['_6', 'a8', '42']
匹配錨字符(邊界字符):
^:從字符串數據的頭部開始匹配,在開啟了多行模式的情況下(re.M),它可以嘗試匹配每一行的頭部數據
$:從字符串數據的尾部開始匹配,在開啟了多行模式的情況下(re.M),它可以嘗試匹配每一行的尾部數據
\A:從字符串數據的頭部開始匹配,在開啟了多行模式的情況下(re.M),它沒有多行的概念,還是匹配第一行的頭部數據
\Z:從字符串數據的尾部開始匹配,在開啟了多行模式的情況下(re.M),它沒有多行的概念,還是匹配最后一行的尾部數據
補充:
\b:嘗試匹配邊界(左側、右側)數據,如果一旦滿足返回對象(match、list)
\B:先舍棄規定邊界的數據,然后一定滿足從左側開始匹配數據,...
代碼演示:
1 import re 2 3 print(re.search(r'^www','hahawww.qfedu.comhehe')) # None,search改成match效果一樣 4 print(re.search(r'^haha','hahawww.qfedu.comhehe')) # <_sre.SRE_Match object; span=(0, 4), match='haha'>,search改成match效果一樣 5 print(re.search(r'hehe$','hahawww.qfedu.comhehe')) # <_sre.SRE_Match object; span=(17, 21), match='hehe'> 6 print(re.search(r'.com$','hahawww.qfedu.comhehe')) # None 7 8 print(re.findall(r'hehe','hahawww.heheqfedu.comhehe')) # ['hehe', 'hehe'] 9 print(re.findall(r'hehe$','hahawww.heheqfedu.comhehe')) # ['hehe'] 10 11 12 print(re.search(r'\Awww','hahawww.qfedu.comhehe')) # None 13 print(re.search(r'\Ahaha','hahawww.qfedu.comhehe')) # <_sre.SRE_Match object; span=(0, 4), match='haha'> 14 print(re.search(r'hehe\Z','hahawww.qfedu.comhehe')) # <_sre.SRE_Match object; span=(17, 21), match='hehe'> 15 print(re.search(r'.com\Z','hahawww.qfedu.comhehe')) # None
演示匹配邊界字符單行與多行的區別:
1 str1 = '''Tom is a good man 2 Tom is a nice man 3 Tom is a cool man 4 Tom is real man''' 5 6 print(re.findall(r'^Tom',str1,flags=re.M)) # ['Tom', 'Tom', 'Tom', 'Tom'] 7 print(re.findall(r'\ATom',str1,flags=re.M)) # ['Tom'] 8 print(re.findall(r'man$',str1,flags=re.M)) # ['man', 'man', 'man', 'man'] 9 print(re.findall(r'man\Z',str1,flags=re.M)) # ['man']
代碼演示\b和\B:
1 # \b相當於^ 和 $ 兩者的作用 2 print(re.search(r'\bne','never')) # <_sre.SRE_Match object; span=(0, 2), match='ne'> 3 print(re.search(r'ne\b','never')) # None 4 print(re.search(r'er\b','neverer')) # <_sre.SRE_Match object; span=(5, 7), match='er'> 5 6 # \B相當於除去邊界之后再匹配 7 print(re.search(r'er\B','never')) # None 8 print(re.search(r'er\B','nerver')) # <_sre.SRE_Match object; span=(1, 3), match='er'> 9 print(re.search(r'er\B','ernerver'))# <_sre.SRE_Match object; span=(0, 2), match='er'> 10 print(re.search(r'\Ber','ernever')) # <_sre.SRE_Match object; span=(5, 7), match='er'>
匹配多個字符:
以下的一些x,y,n等都是變量名
1).模糊匹配:
x?:表示0個或者1個 取值范圍:[0,1]
x+:表示1個或者多個 取值范圍:[1,無窮大)
x*:表示0個或者多個 取值范圍:[0,無窮大)
【注意事項】:關於以上模糊匹配涉及到的三個符號(?、+、*)都滿足了正則中的貪婪匹配的行為/特點(在確保匹配的前提下,盡可能多的返回數據),如何取消貪婪行為?即最終希望得到的是,在確保匹配的前提下,盡可能少的返回數據,代碼體現:只需在(?、+、*)3個符號后面都顯示的再追加一個?即可。具體理解看代碼示例:
1 import re 2 3 str1 = "aaaaaaacccaaaaaaaaa" 4 5 print(re.search(r'a?',str1).group()) # a 6 print(re.search(r'a??',str1).group()) # 7 print(re.search(r'a+',str1).group()) # aaaaaaa 8 print(re.search(r'a+?',str1).group()) # a 9 print(re.search(r'a*',str1).group()) # aaaaaaa 10 print(re.search(r'a*?',str1).group()) # 11 12 13 print(re.findall(r'a?',str1)) # ['a', 'a', 'a', 'a', 'a', 'a', 'a', '', '', '', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', ''] 14 print(re.findall(r'a??',str1)) # ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''] 15 print(re.findall(r'a+',str1)) # ['aaaaaaa', 'aaaaaaaaa'] 16 print(re.findall(r'a+?',str1)) # ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'] 17 print(re.findall(r'a*',str1)) # ['aaaaaaa', '', '', '', 'aaaaaaaaa', ''] 18 print(re.findall(r'a*?',str1)) # ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''] 19 20 21 # 需求:嘗試匹配的內容為:Tom ... man 22 str2 = ' Tom is a good man Tom is a nice man Tom is a super man' 23 regex1= r' Tom.*man' # 有貪婪行為,中間盡可能一次性多的返回數據 24 regex2 = r' Tom.*?man' # 取消其貪婪行為,每個數據里面數據盡可能少 25 26 lt1 = re.findall(regex1,str2) 27 print(lt1) # [' Tom is a good man Tom is a nice man Tom is a super man'] 28 29 lt2 = re.findall(regex2,str2)
30 print(lt2) # [' Tom is a good man', ' Tom is a nice man', ' Tom is a super man']
2).精確匹配:
n{x}: 將n匹配x次
n{x,}: 將n最少有x次,最多無窮大 范圍:[x,無窮多)
n{x,y}:將n最少有x次,最多有y次 范圍:[x,y]
1 str3 = 'aaaaaaacccaaaaaaaaaa' 2 3 print(re.findall(r'a{5}',str3)) # ['aaaaa', 'aaaaa', 'aaaaa'] 4 print(re.findall(r'a{3}',str3)) # ['aaa', 'aaa', 'aaa', 'aaa', 'aaa'] 5 print(re.findall(r'a{3,}',str3)) # 會盡可能返回多的 ['aaaaaaa', 'aaaaaaaaaa'] 6 print(re.findall(r'a{3,}?',str3)) # 取消貪婪行為 ['aaa', 'aaa', 'aaa', 'aaa', 'aaa'] 7 print(re.findall(r'a{8,10}',str3)) # ['aaaaaaaaaa'] 8 print(re.findall(r'a{8,10}?',str3)) # ['aaaaaaaa']
代碼演示正則驗證qq號:
1 # 要求:1).只能都是數字字符;2).不能以0開頭;3).長度5~12位 2 3 import re 4 5 qq = '12345678' 6 regex = r'^[1-9]\d{4,11}$' 7 pat = re.compile(regex) 8 res = pat.match(qq) 9 if res: 10 print('qq號碼合法,號碼為:%s' %qq) 11 else: 12 print('qq號碼不合法...')
正則中的分組:
分組在正則中的定義體現就是使用(...)進行分組操作,理解為分了一個子組。
好處:1).如果正則表達式的邏輯比較復雜,意味着代碼比較多,如果在適當的部分進行分組就可以提高代碼的閱讀性(更有層次感);2).一旦進行了分組操作,在正則表達式的后半部分內容中很多可能需要使用到子組中的內容; 一旦引用了子組,那么這兩部分的內容(值)就可以保持一致了。
具體了解看代碼演示:
1 phone = '62586666' 2 regex = r'^[1-9]\d{3}(\d)\1{3}$' 3 4 print(re.match(regex,phone)) # <_sre.SRE_Match object; span=(0, 8), match='62586666'> 5 print(re.match(regex,phone).groups()) # 返回子組的內容 ('6',) 6 print(re.match(regex,phone).group()) # 和下面效果一樣 62586666 7 print(re.match(regex,phone).group(0)) # 和上面效果一樣 62586666 8 print(re.match(regex,phone).group(1)) # 第一個子組里面的元祖元素 6 9 10 print(re.match(regex,phone).group(2)) # 出現了下標越界的異常:IndexError,原因是正則中只有1個子組,沒有index=2這一組 11 12 13 phone = '021-53437788' 14 regex = r'^(?P<one>\d{3})(?P<two>-)(?P<three>\d{8})$' 15 16 mo = re.search(regex,phone) 17 print(mo.groups()) #('021', '-', '53437788') 18 print(mo.group()) #021-53437788 19 print(mo.group(0)) #021-53437788 20 print(mo.group(1)) #021 21 print(mo.group(2)) #- 22 print(mo.group(3)) #53437788 23 print(mo.group('one')) #021 24 print(mo.group('two')) #- 25 print(mo.group('three')) #53437788