本節(jié)知識大綱:

一、判斷是否滿足要求
通過正則表達(dá)式判斷文本是否符合要求,主要有兩個函數(shù):
(1)match()
從string首字母開始匹配,string如果包含pattern子串,則匹配成功,返回Match對象,失敗則返回None;
一般用于:完全匹配,用于嚴(yán)格的校驗(yàn)
(2)search()
若string中 包含 pattern子串,則返回Match對象,否則返回None,注意:如果string中存在多個pattern子串,只返回第一個;
一般用于:是否包含,用戶判斷內(nèi)容是否存在。
案例01:
判斷手機(jī)號是否符合規(guī)范?
import re
pattern = re.compile(R"^1[3578]\d{9}$")
match_result = pattern.match(input_number)
if match_result is not None:
print("手機(jī)號碼有效,號碼為:",input_number)
else:
print("手機(jī)號碼無效")
案例02:
查看文本中是否包含134開頭的手機(jī)號碼?
import re
str01 = "hello had you thank you 13412345678 " \
"13498765679 1821209776 good"
pattern = re.compile(r"134\d{8}")
match_result = pattern.search(str01)
if match_result:
print("包含134開頭的手機(jī)號,具體為:",match_result.group(0))
else:
print("不包含")
輸出結(jié)果:
包含134開頭的手機(jī)號,具體為: 13412345678
二、獲取捕獲內(nèi)容
兩種基本方法
(1)findall()
返回 string中所有與pattern相匹配的全部字符串,返回形式為集合;findall方法適用于沒有分組或者非捕獲分組的場景;
案例01:沒有分組的場景
在長字符串中獲取1開頭或者9開頭的數(shù)字
import re
str01 = "Use this toggle to the 2234 9876765 9912 left to manage"
print(re.findall(r"\b[19]\d*\b",str01))
案例02:非捕獲分組的場景
獲取http或者h(yuǎn)ttps開頭,cn或者com結(jié)尾的域名
import re
str01 = "browser uses BBC’s https://www.apple.com If you’re http://www.bt.cn thank you"
print(re.findall(r"\b(?:http|https)[:/\w.]*(?:cn|com)\b",str01))
(2)finditer()
返回string中所有與pattern相匹配match對象的迭代,finditer適用的場景為捕獲分組的場景;
案例:獲取4個數(shù)字其中前兩個數(shù)字是一樣的
import re
str01 = "Use this toggle to the 2234 9876765 9912 left to manage"
match_reslut = re.finditer(r"\b(\d)\1\d{2}\b",str01)
match_list = []
for i in match_reslut:
match_list.append(i.group(0))
print(match_list)
獲得的對象通過for進(jìn)行迭代,獲取內(nèi)容通過group(0),由此可見只要涉及了對捕獲組的調(diào)用就不能使用findall()進(jìn)行內(nèi)容獲取,只能通過finditer()進(jìn)行迭代獲取。
三、正則匹配修飾符
通過修飾符來簡化我們對正則表達(dá)式的寫法,正則匹配修飾符有:

我們主要掌握忽略大小寫和多行模式的修飾符的用法就行了,這些正則匹配修飾符主要寫在
findall(正則表達(dá)式,待匹配字符串,匹配修飾符)
1. 使用修飾符忽略大小寫
案例:找出字符串中hello,忽略大小寫
import re
str01 = "Use this toggle to hello the 2234 9876765 Hello 9912 left to hEllO manage how your " \
"browser heLlo uses BBC’s https://www.apple.com "
print(re.findall(r"\bhello\b",str01,re.I)) # 忽略大小寫
如果不使用正則匹配修飾符的話,忽略大小寫,正則表達(dá)式寫的麻煩一點(diǎn),因?yàn)橐汛笮懙那闆r都寫上。
輸出結(jié)果:
['hello', 'Hello', 'hEllO', 'heLlo']
2. 使用修飾符啟用多行模式
案例:找出多行字符串中的hello
import re
str01 = "hello\nhello\nhello\nHello"
print(re.findall(r"^hello",str01)) # 雖然str01是多行,但是開始位置只有一個
print(re.findall(r"^hello",str01,re.M)) # 每一行都進(jìn)行匹配
輸出結(jié)果:
['hello']
['hello', 'hello', 'hello']
四、match對象
通過match()和search()返回match對象,通過finditer()返回的是迭代的match對象
重要:match()是從string字符串的開頭開始匹配,search()只有string字符串中包含了pattern就可以匹配到。比如re.march(r"\d+","abcde123abc")因?yàn)閟tring字符串中數(shù)字123不是在開頭,所以匹配不到,如果換成search方法就可以匹配到數(shù)字123了。
常見方法:
(1)group()獲得一個或多個分組截獲的字符串,編號0代表整個匹配的子串;不填寫參數(shù)時,返回group(0);沒有截獲字符串的組返回None;
案例:
import re
match_result = re.search(r"\d+","abcde123abc")
print(match_result)
# 1. group() 可以空參數(shù)也可以寫0,因?yàn)槟J(rèn)參數(shù)就是0
print(match_result.group(0))
輸出結(jié)果即為匹配的數(shù)字:123
疑問:在正則匹配過程中,我們沒有做任何分組,為何能通過group能訪問到結(jié)果呢?
回答:正則中默認(rèn)整體就是一個分組,編號為0,group(0)返回整個匹配的結(jié)果。
(2)groups()以元組的形式返回全部分組截獲的字符串,default表示沒有截獲字符串的組以這個值替代,默認(rèn)為None
代碼示例:
import re
str01 = "my name is abc123abc"
match_result = re.search(R"\b([a-z]+)([0-9]+)([a-z]+)\b",str01)
print(match_result.groups())
輸出結(jié)果:
('abc', '123', 'abc')
(3)start()匹配開始的索引;
返回指定的組截獲的子串在string中的起始索引(子串第一個字符的索引)。group默認(rèn)值為0。
(4)end()匹配結(jié)束索引;
返回指定的組的子串在string中的結(jié)束索引(子串第一個字符的索引)group默認(rèn)值為0。
(5)span()返回開始索引和結(jié)束索引;
(start(group),end(group)).
代碼示例:
import re
str01 = "my name is abc123abc"
match_result = re.search(R"\b([a-z]+)([0-9]+)([a-z]+)\b",str01)
print(match_result.start())
print(match_result.end())
print(match_result.span())
輸出結(jié)果:
11
20
(11, 20)
五、split函數(shù)
在字符串處理中我們經(jīng)常使用split方法來進(jìn)行字符串的切割,同樣在正則表達(dá)式中也有用split方法來進(jìn)行切割
1. 字符串的切割
如果我們希望根據(jù)字符串中的逗號將字符串切割,tomi,abby,aliy,peter,joel,在傳統(tǒng)的字符串處理方法中使用split方法就可以實(shí)現(xiàn):
str01 = "steven,abby,aliy,peter"
name_list = str01.split(",")
print(name_list)
輸出結(jié)果:
['tomi', 'abby', 'aliy','peter','joel']
但是字符串中的split方法傳入的分隔符只能有一個,對于這種tomi,abby|aliy-peter;joel分割符有很多種符字符串該怎么分割呢?
實(shí)際上,可以使用正則表達(dá)式的split方法,它可以支持多個分割符,只要用|分開就可以了
import re
str01 = "tomi,abby|aliy-peter;joel"
name_list = re.split(",|;|-|\|",str01)
print(name_list)
輸出結(jié)果:
['tomi', 'abby', 'aliy','peter','joel']
2. 分割后的處理
如果我們要處理的字符串分隔符有多個,類似這樣tomi,,,abby|||aliy-peter;;;;joel,分割處理后會出現(xiàn)這樣的結(jié)果:
['tomi', '', '', 'abby', '', '', 'aliy', 'peter', '', '', '', 'joel']
不利于我們對后期數(shù)據(jù)的一個總結(jié),所以我們可以去除空的內(nèi)容,我們可以這樣寫:
name_list =[i for i in re.split(",|;|-|\|",str01) if i] # 如果i非空則保存
這樣就去除了空格輸出的結(jié)果就好看了
['tomi', 'abby', 'aliy', 'peter', 'joel']
六、sub函數(shù)和subn函數(shù)
這兩個函數(shù)主要用于文本中符合我們正則表達(dá)式的內(nèi)容進(jìn)行替換;
sub()函數(shù)主要有四個重要的參數(shù):
sub(pattern,repl,str,count)
- pattern 正則表達(dá)式編譯后的對象
- repl 想要替換成的文本
- str 替換前的文本
- count 替換的次數(shù),如果不寫的話全部替換
返回的是替換成功后的文本
案例演示:
把str01中M開頭的手機(jī)號碼后四位替換成****
import re
str01 = "Use this toggle to the M:13912342234 9876765 9912 left to manage how your " \
"outside the UK M:13789871234 you can also use http://www.bt.cn the toggle to set "
print(re.sub(R"(?<=M:[1][3578]\d{5})\d{4}","****",str01,2))
如果在替換的過程中想使用正則修飾符,可以在四個參數(shù)旁載添加參數(shù)flags=re.I表示忽略大小寫。
使用subn()函數(shù),其傳入的參數(shù)和sub()一樣,只不過它返回的是一個元組,包含了兩個元素,一個是替換后的文本,還有一個是替換的次數(shù)。