21、正則表達(dá)式 正則表達(dá)式時(shí)用來干嘛的?主要是用來匹配字符串的。由于字符串提供的匹配方法是完全匹配。而在實(shí)際情況中,我們可能只需要一串字符串中的某一部分,這時(shí),正則表達(dá)式就非常有用了,可以實(shí)現(xiàn)模糊匹配。 (1)、元字符:. ^ $ * + ? {} | () \ <1> 元字符: . (通配符) import re# ret = re.findall('w..l','Hello world')#.只能代替任意一個(gè)字符# print(ret)#['worl']# ret = re.findall('w.l','Hello w\nld')#.不能代替 \n# print(ret)#[] 未能匹配成功 <2> 元字符:^ (從被匹配字符串的開頭開始進(jìn)行匹配) import re# ret = re.findall('^h...o','hkslhelloadfas') #從被匹配字符串的開頭開始進(jìn)行匹配# print(ret)#[]
<3> 元字符:$ (從被匹配字符串的末尾開始進(jìn)行匹配) import re# ret = re.findall('a..x$','sdfalex')#從被匹配字符串的末尾開始進(jìn)行匹配# print(ret)#['alex'] <4> 元字符:* (重復(fù)匹配:[0,+∞]) import re# ret = re.findall('a.*li','adfdalexasli')# print(ret)#['adfdalexasli']# ret = re.findall('ba*','afdafbadafbaaaaa')# print(ret)#['ba', 'baaaaa']
<5> 元字符:+(重復(fù)匹配:[1,+∞]) import re# ret = re.findall('ab+','afdafdsa')#a后面至少有一個(gè)b才能進(jìn)行匹配# print(ret)#[] <6> 元字符:? (重復(fù)匹配:[0,1]) import re# ret = re.findall('a?b','aaaabhgabdfabfb')#b前面沒有a或者一個(gè)a才能進(jìn)行匹配# print(ret)#['ab', 'ab', 'ab', 'b']
<7> 元字符:{} :(可加匹配范圍) import re# ret = re.findall('a{5}b','abfdsaaaaabdsa')# print(ret)#['aaaaab']# ret = re.findall('a{1,3}b','abfdsaaaaabdsaab')#貪婪匹配 {1,}代表著{1,+∞}# print(ret)#['ab', 'aaab', 'aab'] 總結(jié):*等價(jià)于{0,+∞},+等價(jià)于{1,+∞} ,?等價(jià)于{0,1} <8>元字符 :[ ](字符集) impot re#ret = re.findall('a[c,d,e]x','acx')#可匹配出acx或adx或aex# ret = re.findall('[a-z]','acx')#可匹配出a-z中的所有字母# print(ret)#acx
[ ]:還可以取消元字符的特殊功能,但是這三個(gè)元字符:\ ^ - 例外 import re# ret = re.findall('[w,*]','awds*')# 把*在正則中的特殊功能抹去了,只是一個(gè)普通字符*# print(ret)# ret = re.findall('[0-9,a-z,A-Z]','12tyAs')# - 依舊保持了原來的功能,表示范圍# print(ret)#['1', '2', 't', 'y', 'A', 's']# ret = re.findall('[^t]','fdsaetdaed')#此時(shí)的^,表示取反,即除去t以外的字符全部取出# print(ret)#['f', 'd', 's', 'a', 'e', 'd', 'a', 'e', 'd']# ret = re.findall('[^t,a]','fdsae45tdaed')#此時(shí)的^,表示取反,即除去t和a以外的字符全部取出# print(ret)#['f', 'd', 's', 'e', '4', '5', 'd', 'e', 'd'] <9> 元字符 : \ 注意: 反斜杠后邊跟元字符去除其特殊功能 反斜杠后邊跟普通字符實(shí)現(xiàn)特殊功能 例如: \d: 匹配任何十進(jìn)制數(shù),它相當(dāng)于類[0-9] \D: 匹配任何非數(shù)字字符,相當(dāng)于類[^0-9] \s:匹配任何空白字符,相當(dāng)于類[\t\n\r\f\v] \S:匹配任何非空白字符,相當(dāng)于類[^\t\n\r\f\v] \w:匹配任何字母數(shù)字字符,相當(dāng)于類[a-zA-Z0-9] \W:匹配任何非字母數(shù)字字符,相當(dāng)于類[^a-zA-Z0-9] \b: 匹配一個(gè)特殊字符邊界。 示例: import re''' 反斜杠后邊跟元字符去除其特殊功能 '''ret = re.findall('a\.','a.gjfdsa%fd')print(ret)#['a.']'''反斜杠后邊跟普通字符實(shí)現(xiàn)特殊功能'''print(re.findall('\d{11}','afddsafdsaf123045678954fsfda'))#匹配任何十進(jìn)制數(shù) ['12304567895']print(re.findall('\sasd','fasdd asd'))#[' asd']保證有asd字符串,并且在該字符串的前面有空白字符(空格),輸出時(shí),(空格)一并輸出print(re.findall('\w{2}a','afd9affsasd'))#['d9a', 'fsa']只要有字符a并且在字符a前面保證有兩個(gè)任何字母數(shù)字字符print(re.findall(r'I\b','Hello, I Im a LI%T'))#['I', 'I'] 匹配出單個(gè)字符I,并且要求I后面有一個(gè)特殊字符,前面的r表示用正則表達(dá)式里的語法規(guī)則,前面的一個(gè) r 表示字符串為非轉(zhuǎn)義的原始字符串,讓編譯器忽略反斜杠,也就是忽略換行字符
注意:由于下面連個(gè)原因,在正則表達(dá)式中使用反斜杠就會(huì)產(chǎn)生一個(gè)雙重轉(zhuǎn)換的問題。 ·Python自身處理字符串是,反斜杠是用于轉(zhuǎn)義字符 ·正則表達(dá)式也使用反斜杠來表示轉(zhuǎn)義字符 import reret = re.findall(r'\\','f\j\gfdd')print(ret)#['\\', '\\']'''或者'''ret = re.findall('\\\\','f\j\gfdd')print(ret)#['\\', '\\'] 為什么在匹配規(guī)則中會(huì)出現(xiàn)兩種情況呢?這是因?yàn)?,第一種,是在正則表達(dá)式的語法規(guī)則下進(jìn)行匹配的;而第二種,是通過Python解釋器向正則表達(dá)式語法規(guī)則轉(zhuǎn)換導(dǎo)致的結(jié)果。轉(zhuǎn)換的原則見下圖
示例解析: import res = '123\nabc'#表示:123接一個(gè)換行符再接abc# print(s)#123(換行)abc# print(len(s))#7# ret1_1 = re.subn('\n','x','123\naffd\ndsa')# print(ret1_1)#('123xaffdxdsa', 2)# ret1_2 = re.subn('\\n','x','123\naffd\ndsa')# print(ret1_2)#匹配規(guī)則是一個(gè)換行符('123xaffdxdsa', 2)# ret1_4 = re.subn('\\\\n','x',s)# print(ret1_4)#匹配規(guī)則是一個(gè)反斜杠接n ,未能進(jìn)行匹配('123\nabc', 0)
import rem = r'123\nabc' #表示:123接 一個(gè)反斜杠 再接 nabcprint(m)#123\nabcprint(len(m))#8m1= r'123\\nabc'print(m1)#123\\nabcprint(len(m1))#9ret2_1 = re.subn('\n','x',m)print(ret2_1)#('123\\nabc', 0) 解析: 由于m = r’123\nabc’,其是表示在正則表達(dá)式中的字符串,經(jīng)過轉(zhuǎn)換,在Python解釋器中,實(shí)際的字符串應(yīng)該是’123\nabc’。而,在此行代碼re.subn(‘\n’,’x’,m)中,要匹配的是個(gè)換行符’\n’,并不能進(jìn)行匹配,所以最終結(jié)果是(‘123\nabc’, 0) import reret2_1_1 = re.subn('\\n','x',m)print(ret2_1_1)#('123\\nabc', 0)
解析: re.subn(‘\n’,’x’,m)這行代碼中,要匹配的是’\n’,所以也無法匹配。 至于為什么’\n’—>’\n’,是因?yàn)閞e模塊和Python解釋器之間的轉(zhuǎn)換關(guān)系決定的。如要實(shí)現(xiàn)替換,該如何呢?見下面的代碼 import reret2_1_2 = re.subn('\\\\n','x',m)print(ret2_1_2)#('123xabc', 1)ret2_2 = re.subn(r'\\n','x',m)print(ret2_2)#('123xabc', 1) <10>元字符:( )(分組) |(或) import re# print(re.search('(ad)+','dfadads').group())#adad# print(re.search('(ad)|3','dfad3s').group())#adprint(re.search('(ad)|3','dfas3s').group())#3# ret = re.search('(?P<id>\d{3})/(?P<name>\w{3})','www333/ddd')# print(ret.group())# print(ret.group('id'))# print(ret.group('name'))
(2)、正則表達(dá)式的處理函數(shù) <1>findall(匹配的正則表達(dá)式 , 要匹配的字符串)把匹配到的所有結(jié)果返回到一個(gè)列表中 <2>search(匹配的正則表達(dá)式 , 要匹配的字符串)返回一個(gè)對(duì)象(object),對(duì)象可以調(diào)用group()返回結(jié)果,返回匹配到的第一個(gè)對(duì)象。 示例: import re# ret = re.search('sb','dsasbdsba')# print(ret)#<_sre.SRE_Match object; span=(3, 5), match='sb'># print(ret.group())#sb <3>match(匹配的正則表達(dá)式 , 要匹配的字符串):只在字符串開始匹配,也返回一個(gè)對(duì)象(object),對(duì)象可以調(diào)用group()返回結(jié)果,返回匹配到的第一個(gè)對(duì)象。 示例: import re#print(re.match('asd','hgdkasd'))#None# ret = re.match('asd','asdhhafeasd')# print(ret)#<_sre.SRE_Match object; span=(0, 3), match='asd'># print(ret.group())#asd
<4>split(匹配的正則表達(dá)式 , 要匹配的字符串):以匹配的正則表達(dá)式為界限,把要匹配的字符串分割,并且不把正則表達(dá)式輸出 示例: # ret = re.split('k','djksal')# print(ret)#['dj', 'sal']# ret = re.split('[k,s]','djkasl')# print(ret)#['dj', 'a', 'l']#k,s都沒有了 <5>sub( )替換 subn( )也是替換,但會(huì)顯示替換的次數(shù) 示例: import re print(re.sub('D.*n','hyq','hfalkdDamondfsakfds'))#hfalkdhyqdfsakfds# print(re.subn('D.{3}n','hyq','hfalkdDamondfsaDamonfdsa'))#('hfalkdhyqdfsahyqfdsa', 2)其中2是指,替換了2次
<6>compile( )編譯 示例: # obj = re.compile('\.com')# ret = obj.findall('dfjksdjfisd.com')# print(ret)#['.com'] (3)Demo # import re# line = 'Cats are smarter than dogs'# matchObj = re.match(r'(.*) are (.*?) .*',line, re.M |re.I)# if matchObj:# print('matchObj.group():',matchObj.group())# print('matchObj.group(1):',matchObj.group(1))# print('matchObj.group(2):',matchObj.group(2))# else:# print('No match!')# '''# 解析:# 首先,這是一個(gè)字符串,前面的一個(gè) r 表示字符串為非轉(zhuǎn)義的原始字符串,讓編譯器忽略反斜杠,也就是忽略轉(zhuǎn)義字符。但是這個(gè)字符串里沒有反斜杠,所以這個(gè) r 可有可無。# (.*) 第一個(gè)匹配分組,.* 代表匹配除換行符之外的所有字符。# (.*?) 第二個(gè)匹配分組,.*? 后面多個(gè)問號(hào),代表非貪婪模式,也就是說只匹配符合條件的最少字符# 后面的一個(gè) .* 沒有括號(hào)包圍,所以不是分組,匹配效果和第一個(gè)一樣,但是不計(jì)入匹配結(jié)果中。# matchObj.group() 等同于 matchObj.group(0),表示匹配到的完整文本字符# matchObj.group(1) 得到第一組匹配結(jié)果,也就是(.*)匹配到的# matchObj.group(2) 得到第二組匹配結(jié)果,也就是(.*?)匹配到的'''
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
|