1. 程式人生 > >Python基礎----正則表達式和re模塊

Python基礎----正則表達式和re模塊

去除 [ ] 在一起 asd 編程語言 strong 優先級 詳細說明 call

正則表達式

就其本質而言,正則表達式(或 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模塊