Python基礎----正則表達式和re模塊
就其本質而言,正則表達式(或 re)是一種小型的、高度專業化的編程語言,(在Python中)它內嵌在Python中,並通過 re 模塊實現。正則表達式模式被編譯成一系列的字節碼,然後由用 C 編寫的匹配引擎執行。
字符匹配(普通字符,元字符):
1 普通字符(完全匹配):大多數字符和字母都會和自身匹配
1 >>> import re 2 >>> res=‘hello world good morning‘ 3 >>> re.findall(‘hello‘,res) 4 [‘hello‘]
2 元字符(模糊匹配):. ^ $ * + ? { } [ ] | ( ) \
元字符
. 通配符,匹配一個除了換行符的任意字符,中間如果有換行符也不會跳過換行符,只是無法匹配
1 >>> import re 2 >>> str1="hello\n,張三" 3 #re.findall()方法,第一個元素為匹配規則,第二個元素為字符串,返回的是所有匹配項的列表,re下的方法後面詳細說明 4 >>> re.findall("l",str1) #遍歷匹配l,如果匹配到,則輸出為列表的一個元素 5 [‘l‘, ‘l‘] 6 >>> re.findall("h.",str1) #匹配h開頭,後面包含任意字符除換行符的兩個字符 7 [‘he‘] 8 >>> re.findall("hello.",str1) #因為hello後的字符是換行符,所以匹配不到 9 [] 10 >>> re.findall("張.",str1) #包含的字符串在哪個位置匹配都可以 11 [‘張三‘]
^ 開始匹配,只匹配字符串的開頭,開頭如果沒有,後邊不會再進行匹配
1 >>> re.findall("^hello",str1) #開頭有hello所以匹配成功 2 [‘hello‘] 3 >>> re.findall("^llo",str1) #開頭沒有llo,匹配失敗 4 []
$ 結尾匹配,只匹配結尾
1 >>> re.findall("llo$",str1) #該字符串以三結尾 2 [] 3 >>> re.findall("三$",str1) 4 [‘三‘] 5 >>> re.findall("張三$",str1) #可匹配多個字符 6 [‘張三‘] 7 >>> re.findall("張.$",str1) #不同的元字符聯用 8 [‘張三‘]
重復功能元字符
? 表示?前一個字符或組可有可無,範圍即0次或1次
1 >>> re.findall("ho?el",str1) #o可有可無,匹配hel 2 [‘hel‘] 3 >>> re.findall("he?l",str1) #e可有可無,有的時候匹配hel 4 [‘hel‘] 5 >>> re.findall("he?el",str1) #第一個e可有可無,沒有的時候匹配hel 6 [‘hel‘]
* 表示*前面一個字符或組的重復範圍,範圍從0開始到正無窮,[0,+∞]
1 >>> str2="111111133111188211111111111134234" 2 >>> re.findall("1*",str2) #1*表示字符1出現0次或多次,從字符串依次匹配,如果不是1就用空補全 3 [‘1111111‘, ‘‘, ‘‘, ‘1111‘, ‘‘, ‘‘, ‘‘, ‘111111111111‘, ‘‘, ‘‘, ‘‘, ‘‘, ‘‘, ‘‘] 4 >>> re.findall("11*",str2) #11*表示第二個字符1出現0次或多次,第一個字符1已經固定 5 [‘1111111‘, ‘1111‘, ‘111111111111‘]
+ 類似與*,表示+前面一個字符或組的重復範圍,範圍從1開始到正無窮,[1,+∞]
1 >>> re.findall("11+",str2) #11+表示第二個1必須是出現1次或多次 2 [‘1111111‘, ‘1111‘, ‘111111111111‘] 3 >>> re.findall("1+",str2) #1+表示必須出現一次1及以上 4 [‘1111111‘, ‘1111‘, ‘111111111111‘]
{} {n,m},指定範圍,不指定m表示從n到無窮,只有一個n是只能是這麽多次
1 >>> str2="111111133111188211111111111134234" 2 >>> re.findall("1{4}",str2) #按照字符1重復4次匹配,共匹配成功5次 3 [‘1111‘, ‘1111‘, ‘1111‘, ‘1111‘, ‘1111‘] 4 >>> re.findall("3{2}",str2) #匹配出現2次3的字符串 5 [‘33‘] 6 >>> re.findall("3{1,3}",str2) #匹配出現1到3次3的情況 7 [‘33‘, ‘3‘, ‘3‘] 8 >>> re.findall("1{1,}",str2) #匹配出現1至少一次的情況 9 [‘1111111‘, ‘1111‘, ‘111111111111‘]
轉義字符
\ 反斜杠後邊跟元字符去除特殊功能,反斜杠後邊跟普通字符實現特殊功能
\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 匹配一個特殊字符邊界,比如空格 ,&,#等
字符串:包含特殊字符、數字、大小寫字母及漢字
1 >>> str3=‘123456 7890@#$abcd efg!%&*HIJKLMN陳‘
\d 匹配十進制數
1 >>> re.findall("\d",str3) 2 [‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘, ‘8‘, ‘9‘, ‘0‘]
\D 匹配非數字字符
1 >>> re.findall("\D",str3) 2 [‘ ‘, ‘ ‘, [email protected], ‘#‘, ‘$‘, ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘ ‘, ‘ ‘, ‘e‘, ‘f‘, ‘g‘, ‘!‘, ‘%‘, ‘&‘, ‘*‘, ‘H‘, ‘I‘, ‘J‘, ‘K‘, ‘L‘, ‘M‘, ‘N‘, ‘陳‘]
\s 匹配任何空白字符
>>> re.findall("\s",str3) [‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘]
\S 匹配任何非空白字符
1 >>> re.findall("\S",str3) 2 [‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘, ‘8‘, ‘9‘, ‘0‘, [email protected], ‘#‘, ‘$‘, ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘, ‘g‘, ‘!‘, ‘%‘, ‘&‘, ‘*‘, ‘H‘, ‘I‘, ‘J‘, ‘K‘, ‘L‘, ‘M‘, ‘N‘, ‘陳‘]
\w 匹配任何字母數字漢字字符
1 >>> re.findall("\w",str3) 2 [‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘, ‘8‘, ‘9‘, ‘0‘, ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘, ‘g‘, ‘H‘, ‘I‘, ‘J‘, ‘K‘, ‘L‘, ‘M‘, ‘N‘, ‘陳‘]
\W 匹配任何非字母數字漢字字符
1 >>> re.findall("\W",str3) 2 [‘ ‘, ‘ ‘, [email protected], ‘#‘, ‘$‘, ‘ ‘, ‘ ‘, ‘!‘, ‘%‘, ‘&‘, ‘*‘]
\b 匹配一個特殊的字符邊界,註意:因為\b和py解釋器有沖突,所以需要加上r表示以源生字符方式傳送給re模塊解釋
1 >>> re.findall(r"abcd\b",str3) 2 [‘abcd‘] 3 >>> re.findall(r"123456\b",str3) 4 [‘123456‘]
源生字符r示例1:匹配“abc\le”中的‘c\l’,\l無特殊含義
1 >>> import re 2 >>> str4="abc\le" 3 >>> re.findall(‘c\l‘,‘abc\le‘) #報錯,py解釋器會解釋一次轉義字符,一個\無法解釋 4 >>> re.findall(‘c\\l‘,‘abc\le‘) #報錯,py解釋器將兩個\解釋成一個\傳給re模塊,re模塊
5 >>> re.findall(‘c\\\l‘,‘abc\le‘) #py解釋器將三個\解釋成\\傳給re模塊,re模塊解釋\\轉義匹配c\l 6 [‘c\\l‘] #因為匹配出來的c\l的\是特殊字符,所以py解釋器將\轉義一次輸出 7 >>> re.findall(‘c\\\\l‘,‘abc\le‘) #py解釋器將第一個和第二個\解釋成一個\,第三個第四個\解釋成一個\,共兩個\傳給re模塊 8 [‘c\\l‘] 9 >>> re.findall(r‘c\\l‘,‘abc\le‘) #py解釋器通過r標識,將兩個\解釋為源生字符直接傳給re模塊 10 [‘c\\l‘]
源生字符r示例2:匹配“abc\be”中的‘c\b’,\b有特殊含義,為ascii表的退格
1 >>> str5="abc\be" 2 >>> re.findall(‘c\b‘,‘abc\be‘) 3 [‘c\x08‘] 4 >>> re.findall(‘c\\b‘,‘abc\be‘) 5 [‘c‘] 6 >>> re.findall(‘c\\\b‘,‘abc\be‘) 7 [‘c\x08‘] 8 >>> re.findall(‘c\\\\b‘,‘abc\be‘) 9 [] 10 >>> re.findall(r‘c\b‘,‘abc\be‘) 11 [‘c‘] 12 >>> re.findall(r‘c\\b‘,‘abc\be‘) 13 [] 14 >>> re.findall(r‘c\\\b‘,‘abc\be‘) 15 [] 16 >>> re.findall(r‘c\\\\b‘,‘abc\be‘) 17 [] 18 >>> re.findall(r‘c\b‘,r‘abc\be‘) 19 [‘c‘] 20 >>> re.findall(r‘c\\b‘,r‘abc\be‘) #當字符串內有特殊含義的字符時候,需要加r轉義為源生字符 21 [‘c\\b‘] 22 >>> re.findall(r‘c\\\b‘,r‘abc\be‘) 23 [‘c\\‘] 24 >>> re.findall(r‘c\\\\b‘,r‘abc\be‘) 25 []
() 分為普通分組和命名分組兩種,和的意思,匹配規則的字符串以組的方式劃成一個整體,這個整體賦規則匹配字符串
1 >>> str6="faefhuknghellohellohelloafeahelloadf" 2 >>> re.findall("(hello)+",str6) #將hello組成一個整體進行+規則 3 [‘hello‘, ‘hello‘] #因為優先級的限制,只能顯示分組內的內容 4 >>> re.findall("(?:hello)+",str6) 5 [‘hellohellohello‘, ‘hello‘] #?:是一個格式,取消優先級限制,將匹配到的所有顯示出來
分組一般配合re.search()和re.match()方法調用
re.search()格式和findall相同,但是其返回的是一個對象,通過調用對象的group方法返回具體的值,re.search()只會匹配一次值,匹配到之後將不再向後匹配,即只有一個結果。
1 >>> re.search("(hello)+",str6) 2 <_sre.SRE_Match object; span=(9, 24), match=‘hellohellohello‘> 3 >>> ret=re.search("(hello)+",str6) 4 >>> ret.group() 5 ‘hellohellohello‘
re.match()方法和元字符^的功能類似,匹配字符串開頭,返回一個對象,並且也能通過group方法返回具體的值
1 >>> str7="hellohellohellonameafeahelloadf" 2 >>> ret=re.match("(hello)+",str7) #開頭有hello能匹配到 3 >>> ret.group() 4 ‘hellohellohello‘ 5 >>> ret=re.match("(name)+",str7) #開頭沒有name,匹配不到 6 >>> ret.group() 7 Traceback (most recent call last): 8 File "<stdin>", line 1, in <module> 9 AttributeError: ‘NoneType‘ object has no attribute ‘group‘
命名分組:在分組的基礎上加上一個名字,通過group方法調用分組名字返回具體的值
1 >>> str8="-blog-aticles-2015-04" 2 >>> ret=re.search(r"-blog-aticles-(?P<year>\d+)-(?P<month>\d+)",str8) #?P是定義命名的格式,<>內是名字 3 >>> ret.group(‘year‘) 4 ‘2015‘ 5 >>> ret.group(‘month‘) 6 ‘04‘
[] 字符集,中括號內的字符集合,關系為或,即匹配括號內任意一個字符即可,字符集內的-^\三個字符具有特殊意義,其他字符喪失原來的特殊意義。
1 >>> str9="adf13415aggae8657dfc" 2 >>> re.findall("a[dg]+",str9) #匹配a開頭,後面多余一個d或者g結尾的部分 3 [‘ad‘, ‘agg‘]
字符集內的-表示一個範圍
1 >>> re.findall("[0-9]+",str9) #包含0-9數字的字符,匹配+規則 2 [‘13415‘, ‘8657‘] 3 >>> re.findall("[a-z]+",str9) 4 [‘adf‘, ‘aggae‘, ‘dfc‘]
字符集內的^表示取反
1 >>> re.findall("[^a-z]+",str9) #不是包含a-z字母的字符,匹配+規則 2 [‘13415‘, ‘8657‘] 3 >>> re.findall("[^0-9]+",str9) 4 [‘adf‘, ‘aggae‘, ‘dfc‘]
字符集內的\表示轉義
1 >>> re.findall("[\d]",str9) 2 [‘1‘, ‘3‘, ‘4‘, ‘1‘, ‘5‘, ‘8‘, ‘6‘, ‘5‘, ‘7‘] 3 >>> re.findall("[\w]",str9) 4 [‘a‘, ‘d‘, ‘f‘, ‘1‘, ‘3‘, ‘4‘, ‘1‘, ‘5‘, ‘a‘, ‘g‘, ‘g‘, ‘a‘, ‘e‘, ‘8‘, ‘6‘, ‘5‘, ‘7‘, ‘d‘, ‘f‘, ‘c‘]
| 管道符號,表示或
1 >>> str10="www.oldboy.com;www.oldboy.cn;www.baidu.com;" 2 >>> re.findall("www\.(?:\w+)\.(?:com|cn)",str10) 3 [‘www.oldboy.com‘, ‘www.oldboy.cn‘, ‘www.baidu.com‘]
貪婪匹配和非貪婪匹配(基於重復)
貪婪匹配:按照最長的結果匹配
1 >>> str11="dasa11s6666dabccccasd" 2 >>> re.findall("abc+",str11) #+表示從範圍從1到正無窮,所以多少個c都可以匹配到 3 [‘abcccc‘] 4 >>> re.findall("\d+",str11) 5 [‘11‘, ‘6666‘]
非貪婪匹配:按照最短的結果匹配
1 >>> re.findall("\d+?",str11) #在+後面加?表示取最小範圍1 2 [‘1‘, ‘1‘, ‘6‘, ‘6‘, ‘6‘, ‘6‘] 3 >>> re.findall("abc+?",str11) 4 [‘abc‘]
非貪婪應用示例:
1 >>> str12="<div>yuan<img></div><a href=""></div>" 2 >>> re.findall("<div>.*?</div>",str12) #匹配到第一個</div> 3 [‘<div>yuan<img></div>‘]
非貪婪匹配規則:
1 *? 重復任意次,但盡可能少重復 2 +? 重復1次或更多次,但盡可能少重復 3 ?? 重復0次或1次,但盡可能少重復 4 {n,m}? 重復n到m次,但盡可能少重復 5 {n,}? 重復n次以上,但盡可能少重復
.*?用法:
1 . 是任意字符 2 * 是取 0 至 無限長度 3 ? 是非貪婪模式。 4 合在一起就是取盡量少的任意字符,一般不會這麽單獨寫,他大多用在:“.*?a”,就是取前面任意長度的字符,到最後一個 a 出現
re模塊方法
re.findall()方法:匹配所有,將匹配到的結果全部按照列表方式返回
re.search()方法:返回一個對象,通過group方法調用具體值,示例見分組部分,匹配到第一個就不再往下繼續匹配了,沒匹配到返回一個None
re.match()方法:只在字符串開始的位置匹配,返回的是一個對象,通過group方法調用具體值,示例見分組部分
re.split()方法:分割,以列表方式返回,中間用正則模糊匹配,可以限定分割次數
1 >>> str13="hello23world12my7name" 2 >>> re.split("\d+",str13) #以數字為分割線,返回其他值 3 [‘hello‘, ‘world‘, ‘my‘, ‘name‘] 4 >>> re.split("(\d+)",str13) #同時返回分割線 5 [‘hello‘, ‘23‘, ‘world‘, ‘12‘, ‘my‘, ‘7‘, ‘name‘] 6 >>> re.split("\d+",str13,1) #分割一次 7 [‘hello‘, ‘world12my7name‘]
特殊情況,分割出空
1 >>> re.split("l","hello bob") 2 [‘he‘, ‘‘, ‘o bob‘]
re.sub()方法:替換,格式為:規則-替換內容-字符串-計數限定次數
1 >>> str14="hello 123 123 name world my name " 2 >>> re.sub("\d+","A",str14) 3 ‘hello A A name world my name ‘ 4 >>> re.sub("\d","A",str14) 5 ‘hello AAA AAA name world my name ‘ 6 >>> re.sub("\d","A",str14,3) 7 ‘hello AAA 123 name world my name ‘
re.subn():類似於sub,但是以元組返回,並且返回替換次數
1 >>> re.subn("\d","A",str14,3) 2 (‘hello AAA 123 name world my name ‘, 3)
re.finditer():返回一個叠代器,調用也是要group方法
1 >>> ret=re.finditer("\d+","dasfjk324khk4234kj234hkj234hkj234kj234k2j34hk2j3h4") 2 >>> print(ret) 3 <callable_iterator object at 0x000001CE69609470> 4 >>> print(next(ret)) 5 <_sre.SRE_Match object; span=(6, 9), match=‘324‘> 6 >>> print(next(ret).group()) #因為已經叠代了一次,所以返回第二個值 7 4234
re.compile():編譯規則,以編譯對象的方式調用,頻繁調用同一個規則時候使用
1 >>> num_rule=re.compile(‘\d+‘) 2 >>> print(num_rule,type(num_rule)) 3 re.compile(‘\\d+‘) <class ‘_sre.SRE_Pattern‘> 4 >>> num_rule.findall("hello 123 3241") 5 [‘123‘, ‘3241‘]
Python基礎----正則表達式和re模塊