Python正則表達式
Python正則表達式
1.正則表達式字符串是由普通字符和元字符表示。

①元字符 ②普通字符
基本元字符
| 字符 | 說明 |
|---|---|
| \ | 轉(zhuǎn)義符,表示轉(zhuǎn)義 |
| . | 表示任意一個字符 |
| + | 表示重復(fù)一次或多次 |
| * | 表示重復(fù)零次或多次 |
| ? | 表示重復(fù)零次或一次 |
| | | 選擇符號,表示“或關(guān)系“,例如:A|B表示匹配A或B |
| 定義量詞 | |
| [ ] | 定義字符類 |
| ( ) | 定義分組 |
| ^ | 可以表示取反,或匹配一行的開始 |
| $ | 匹配一行的結(jié)束 |
當以^開始時,要求一行字符串的開始位置匹配;當以$結(jié)束時,要求一行字符串的結(jié)束位置匹配。所以正則表達式\w+@zhi jieketang\.com和^\w+@zhi jieketang\.com$是不同的。
import re
p1=r'\w+@zhijieketang\.com'
p2=r'^\w+@zhijieketang\.com$'
text = "Tony's email is tony_guan588@zhijieketang.com."
m = re.search(p1,text)
print(m)
m = re.search(p2,text)
print(m)
email = 'tony_guan588@zhijieketang.com'
m = re.search(p2,email)
print(m)
函數(shù)
re.match 嘗試從字符串的起始位置匹配一個模式,如果不是起始位置匹配成功的話,match()就返回none。
import re
print(re.match('www', 'www.runoob.com').span()) # 在起始位置匹配
print(re.match('com', 'www.runoob.com')) # 不在起始位置匹配
#輸出結(jié)果
(0,3)
None
re.search 掃描整個字符串并返回第一個成功的匹配。
import re
print(re.search('www', 'www.runoob.com').span()) # 在起始位置匹配
print(re.search('com', 'www.runoob.com').span()) # 不在起始位置匹配
#輸出結(jié)果
(0, 3)
(11, 14)
re.match只匹配字符串的開始,如果字符串開始不符合正則表達式,則匹配失敗,函數(shù)返回None;而re.search匹配整個字符串,直到找到一個匹配。
findall在字符串中找到正則表達式所匹配的所有子串,并返回一個列表,如果沒有找到匹配的,則返回空列表。
import re
pattern = re.compile(r'\d+') # 查找數(shù)字
result1 = pattern.findall('runoob 123 google 456')
result2 = pattern.findall('run88oob123google456', 0, 10)
print(result1)
print(result2)
#輸出結(jié)果
['123', '456']
['88', '12']
re.finditer和 findall 類似,在字符串中找到正則表達式所匹配的所有子串,并把它們作為一個迭代器返回。
import re
it = re.finditer(r"\d+","12a32bc43jf3")
for match in it:
print (match.group() )
# 輸出結(jié)果
12
32
43
3
split 方法按照能夠匹配的子串將字符串分割后返回列表,它的使用形式如下:
re.split(pattern, string[, maxsplit=0, flags=0])
pattern:匹配的正則表達式
string:要匹配的字符串。
maxsplit:分隔次數(shù),maxsplit=1 分隔一次,默認為 0,不限制次數(shù)。
flags:標志位,用于控制正則表達式的匹配方式,如:是否區(qū)分大小寫,多行匹配等等。
import re
p = r'\d+'
text = 'AB12CD34EF'
clist = re.split(p,text)
print(clist)
clist = re.split(p,text,maxsplit=1) #最大分隔一次
print(clist)
clist = re.split(p,text,,maxsplit=2) #最大分隔兩次
print(clist)
#輸出結(jié)果
['AB','CD','EF']
['AB','CD34EF']
['AB','CD','EF']
re.sub用于替換字符串中的匹配項。
re.sub(pattern, repl, string, count=0, flags=0)
- pattern : 正則中的模式字符串。
- repl : 替換的字符串,也可為一個函數(shù)。
- string : 要被查找替換的原始字符串。
- count : 模式匹配后替換的最大次數(shù),默認 0 表示替換所有的匹配。
import re
p = r'\d+'
text = 'AB12CD34EF'
repace_text = re.sub(p,'',text)
print(repace_text)
#輸出結(jié)果
ABCDEF
compile 函數(shù)用于編譯正則表達式,生成一個正則表達式( Pattern )對象,供 match() 和 search() 這兩個函數(shù)使用。編譯的正則表達式可以重復(fù)使用,減少正則表達式解析和驗證,提高效率。
re.compile(pattern[, flags])
- pattern : 一個字符串形式的正則表達式
- flags : 可選,表示匹配模式,比如忽略大小寫,多行模式等,具體參數(shù)為:
- re.I 忽略大小寫
- re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依賴于當前環(huán)境
- re.M 多行模式
- re.S 即為 . 并且包括換行符在內(nèi)的任意字符(. 不包括換行符)
- re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依賴于 Unicode 字符屬性數(shù)據(jù)庫
- re.X 為了增加可讀性,忽略空格和 # 后面的注釋
>>>import re
>>> pattern = re.compile(r'\d+') # 用于匹配至少一個數(shù)字
>>> m = pattern.match('one12twothree34four') # 查找頭部,沒有匹配
>>> print m
None
>>> m = pattern.match('one12twothree34four', 2, 10) # 從'e'的位置開始匹配,沒有匹配
>>> print m
None
>>> m = pattern.match('one12twothree34four', 3, 10) # 從'1'的位置開始匹配,正好匹配
>>> print m # 返回一個 Match 對象
<_sre.SRE_Match object at 0x10a42aac0>
>>> m.group(0) # 可省略 0
'12'
>>> m.start(0) # 可省略 0
3
>>> m.end(0) # 可省略 0
5
>>> m.span(0) # 可省略 0
(3, 5)
字符類
正則表達式中可以使用字符類,一個字符類定義一組字符,其中的任一字符出現(xiàn)在輸出字符串中即匹配成功。注意每次匹配只能匹配字符類中的一個字符。
1.定義字符類
定義一個普通的字符類需要使用'['和']'元字符類。
import re
# 在輸入字符串中匹配Java或java,可以使用正則表達式[Jj]ava。
p = r'[Jj]ava
m = re.search(p,'I like Java and Python')
print(m)
m = re.search(p,'I like JAVA and Python')
print(m)
m = re.search(p,'I like java and Python')
print(m)
2.字符類取反
有時需要在正則表達式中指定不想出現(xiàn)的字符,可以在字符類前加"^"符號。
import re
#表示非數(shù)字
p = r'[^0123456789]''
m = re.search(p,'1000')
print(m)
m = re.search(p,'Python 3')
print(m)
#遇到第一個匹配的就返回
3.區(qū)間
區(qū)間是用連字符(-)表示的,[0123456789]采用區(qū)間表示[0-9],[^0123456789]采用區(qū)間表示[^0-9]。[A-Za-z0-9]表示任何字母和數(shù)值字符類,[0-25-7]表示0、1、2、5、6、7幾個字符組成的字符類。
import re
m = re.search(r'[A-Za-z0-9]'','A10.3')
print(m)
m = re.search(r'[0-25-7],'A34879C')
print(m)
#輸出結(jié)果
<_sre.SRE_Match object;span=(0,1),match='A'>
<_sre.SRE_Match object;span=(4,5),match='7'>
4.預(yù)定義字符類
| 字符 | 說明 |
|---|---|
| . | 匹配任意一個字符 |
| \\ | 匹配反斜杠\字符 |
| \n | 匹配換行 |
| \r | 匹配回車 |
| \f | 匹配一個換頁符 |
| \t | 匹配一個水平制表符 |
| \v | 匹配一個垂直制表符 |
| \s | 匹配任何空白字符,包括空格、制表符、換頁符等等。等價于 [ \f\n\r\t\v]。 |
| \S | 匹配任何非空白字符。等價于 [^ \f\n\r\t\v]。 |
| \d | 匹配一個數(shù)字字符。等價于 [0-9]。 |
| \D | 匹配一個非數(shù)字字符。等價于 [^0-9]。 |
| \w | 匹配任何語音的單詞字符(如:英文字母、亞洲文字等)、數(shù)字和下劃線(_)等字符。如果正則表達式編譯標志設(shè)置為ASCII,則只匹配'[A-Za-z0-9_]'。 |
| \W | 等價于 '[^\w]'。 |
量詞
表示字符或字符串重復(fù)的次數(shù)。
| 字符 | 說明 |
|---|---|
| ? | 出現(xiàn)零次或一次 |
| * | 出現(xiàn)零次或多次 |
| + | 出現(xiàn)一次或多次 |
| 出現(xiàn)零次或n次 | |
| 至少出現(xiàn)n次但不超過m次 | |
| 至少出現(xiàn)n次 |
貪婪量詞會盡可能多地匹配字符;懶惰量詞盡可能少地匹配字符。大多數(shù)計算機語言的正則表達式量詞默認是貪婪的,要想使用懶惰量詞可以在量詞后面加“?”即可。
import re
# 使用貪婪量詞
m = re.search(r'\d{5,8}','87654321') #出現(xiàn)數(shù)字8次
print(m) #匹配字符'87654321'
# 使用惰性量詞
m = re.search(r'\d{5,8}?','87654321') #出現(xiàn)數(shù)字5次
print(m) #匹配字符'87654'
#輸出結(jié)果
<_sre.SRE_Match object;span=(0,8),match='87654321'>
<_sre.SRE_Match object;span=(0,5),match='87654'>
分組
如果想讓一個字符串作為整體使用量詞,可將這個字符串放到一對小括號中,這就是分組。
import re
p = r'(121){2}''
m = re.search(p,'121121abcabc')
print(m)
print(m.group()) #返回匹配的字符串
print(m.groups()) #返回所有組的內(nèi)容
p = r'(\d{3,4})-(\d{7,8})'
m = re.search(p,'010-87654321')
print(m)
print(m.group()) #返回匹配的字符串
print(m.groups())
# 輸出結(jié)果
<_sre.SRE_Match object;span=(0,6),match='121121'>
121121
('121',)
<_sre.SRE_Match object;span=(0,12),match='010-87654321'>
010-87654321
('010','87654321')
1.對正則表達式進行分組不僅可以對一個字符串整體使用量詞,還可以在正則表達式中引用已經(jīng)存在的分組。
2.在Python程序中訪問分組時,除了可以通過組編號進行訪問,還可以通過組名進行訪問,前提是要在正則表達式中為組命名。組命名語法是在分組的左小括號后添加?P<分組名>實現(xiàn)。
3.反向引用分組。除了可以在程序代碼中訪問正則表達式匹配之后的分組內(nèi)容,還可以在正則表達式內(nèi)部引用之前的分組。
import re
p = r'<([\w]+)>.*</\1>'
m = re.search(p,'<a>abc</a>')
print(m)
m = re.search(p,'<a>abc</b>')
print(m)
# 輸出結(jié)果
<_sre.SRE_Match object;span=(0,10),match='<a>abc</a>'>
None
4.非捕獲分組
前面介紹的分組稱為捕獲分組,就是匹配子表達式結(jié)果被暫時保存到內(nèi)存中,以被表達式或其他程序引用,這稱之為“捕獲”,捕獲結(jié)果可以通過組編號或組名進行引用。但是有時并不想引用子表達式的匹配結(jié)果,不想捕獲匹配結(jié)果,只是將小括號作為一個整體進行匹配,此時可以使用非捕獲分組,非捕獲分組在組開頭使用“?:"實現(xiàn)。
import re
s = 'img1.jpg,img2.jpg,img3.bmp'
p = r'\w+(\.jpg)'
m = re.findall(p,s)
print(m)
p = r'\w+(?:\.jpg)'
m = re.findall(p,s)
print(m)
#輸出結(jié)果
['.jpg','.jpg']
['img1.jpg','img2.jpg']
浙公網(wǎng)安備 33010602011771號