正則表達式
-
python無正則表達式,通過別的模塊re(regex模塊)應用過來
- import re # 引入re模塊調(diào)用正則表達式
-
字符匹配
- 普通字符:如英文字母a-zA-Z和其他字符
regex = 'apple' ret = re.findall(regex, 'i have a apple , i have a pen, apple pen ?') print(ret) ======> ['apple', 'apple']
-
元字符:被賦予特殊含義的字符
- .:通配符(任意字符)
- ^:是否以某個字符開頭
- $:是否以某個字符結尾
ret = re.findall('.', 'string') print(ret) # ['s', 't', 'r', 'i', 'n', 'g'] ret = re.findall("^apple", 'apple is one kind of fruit') print(ret) # ['apple'] ret = re.findall("^apple", 'the apple is one kind of fruit') print(ret) # [] ret = re.findall('pen$', 'i have a apple , i have a pen, apple pen ?') print(ret) # [] ret = re.findall('pen$', 'i have a apple , i have a pen, apple pen') print(ret) # ['pen']
- * :出現(xiàn)0次或n次
- +:出現(xiàn)1次或n次
- ?:出現(xiàn)0次或1次
- {}:
- {x}:出現(xiàn)x次
- {x,}:至少出現(xiàn)x次
- {x,y}:出現(xiàn)x-y次之間
ret = re.findall('apple*', 'i have an apple , not applee or appl') print(ret) # ['apple', 'applee', 'appl'] ret = re.findall('apple+', 'i have an apple , not applee or appl') print(ret) # ['apple', 'applee'] ret = re.findall('apple?', 'i have an apple , not applee or appl') print(ret) # ['apple', 'apple', 'appl'] ret = re.findall('apple{2,4}','i have an apple , not appleee or appleeee') print(ret) # ['appleee', 'appleeee']
- \:轉義
- 后面如果接元字符募逞,則將元字符轉為普通字符
- 后面接普通字符倡怎,則實現(xiàn)該字符特殊功能
- 后面接序號物邑,引用所匹配的字符串
- -:表示范圍
- ^:取反
- \:轉義
- \d:數(shù)字[1-9]
- \D:非數(shù)字[^1-9]
- \w:字母數(shù)字下劃線[a-zA-Z_]
- \W:非字母數(shù)字下劃線[^a-zA-Z_]
- \s:空白字符[\t\n\r\f\v]
- \S:非空白字符[\t\n\r\f\v]
- \b:匹配單個單詞邊界戳杀,就是單詞間間隔,邊界不一定是空格,特殊字符也可以
- ():組
ret = re.findall('\d', '123sadf@#$') print(ret) # ['1', '2', '3'] ret = re.findall('[^\d]+','asdf123d5esd234') print(ret) # ['asdf', 'd', 'esd'] ret = re.search(r'(alex)(eric)com\1', 'alexericcomalex').group() print(ret) # alexericcomalex
- 非貪婪匹配
- 一般 *和+匹配的時候都按照最多的原則匹配獲取(貪婪匹配)
- 如果想要按最少匹配,則加上?但是有條件
\d+?:一個或者多個,取最少的1個 \d*?:0個或者多個,取最少的0個 'a(\d+?)':可以用非貪婪匹配 'a(\d+?)b'不可以用非貪婪模式茬高,因為后面接了字符
-
re包方法:
- findall():查找所有,返回一個列表
- search():找到第一個就不往下找了
- match():只匹配開頭的內(nèi)容
-
search() 和 match()如果匹配成功或返回一個對象,該對象方法
- group():返回組的內(nèi)容
- groups():根據(jù)regex的分組情況返回tuple
ret = re.search('(ap)+(pl)+e', 'apple apaplele').group() print(ret) # apple ret = re.search('(ap)+(pl)+e', 'apple apaplele').groups() print(ret) # ('ap', 'pl')
- start():匹配到的第一個索引位置
- end():匹配的結束位置索引
- span():start 和 end索引之間的區(qū)間
ret = re.search('(ap)+(pl)+e', 'apple apaplele') print(ret.start()) # 從開始 print(ret.end()) # index = 4結束假抄,開區(qū)間為5 print(ret.span()) #[0,5)
a = '123abc456' regex = '([\d]*)([a-zA-Z]*)([\d]*)' ret = re.search(regex, a) print(ret.group()) # 默認為0 print(ret.group(1)) print(ret.group(2)) print(ret.group(3)) print(ret.groups()) """ 123abc456 123 abc 456 ('123', 'abc', '456') """ a = '123abc456' regex = '([\d])*([a-zA-Z])*([\d])*' ret = re.search(regex, a) print(ret.group()) # 默認為0 print(ret.group(1)) print(ret.group(2)) print(ret.group(3)) print(ret.groups()) """ 123abc456 3 c 6 ('3', 'c', '6') """
-
re的其他方法:
- sub(pattern, repl, string, max=0):替換
- max表示替換的最大次數(shù)怎栽,默認為0,不限次數(shù)
ret = re.sub('g.t', 'have', 'i get a pen, i got a pen, i gun a pen') print(ret) # i have a pen, i have a pen, i gun a pen
- subn(pattern, repl, string):替換宿饱,返回的結果帶替換次數(shù)num
ret = re.subn('g.t', 'have', 'i get a pen, i got a pen, i gun a pen') print(ret) # ('i have a pen, i have a pen, i gun a pen', 2)
- compile(regext):編譯.傳入一個正則表達式熏瞄,返回一個匹配器
regex = re.compile('\w*oo\w*') ret = regex.findall('JGood is a handsome boy, he is cool') print(ret) # ['JGood', 'cool']
- split:切割
ret = re.split('\d', 'one1two2three3four4') print(ret) # ['one', 'two', 'three', 'four', '']
- sub(pattern, repl, string, max=0):替換
IP正則表達式
# IP 正則表達式
regex = '(([01]?\d?\d|2[0-4]\d|25\d)\.){3}([01]?\d?\d|2[0-4]\d|25\d)'
ret = re.search(regex, '192.168.97.196').group()
print(ret) # 192.168.97.196
-
原生字符串
- 執(zhí)行下面的代碼會報錯(在python中)
file = open('C:\tmp\abc.txt', mode='r') # OSError: [Errno 22] Invalid argument: 'C:\tmp\x07bc.txt'
-
原因:
- 在python中,反斜杠\有轉義的含義谬以,當遇到\a根據(jù)ascii碼表强饮,會轉為有特殊含義的字符0x07響鈴符BEL
-
解決:
- file = open(r'C:\tmp\abc.txt', mode='r')
- r為rawString = 原生字符串,表示傳入python的字符是原生的为黎,沒有特殊的含義
執(zhí)行下面的代碼會報錯(在正則中)
re.findall('\', 'abc\123') # 編譯的時候就會出錯
-
原因:
- 反斜杠\在正則中也有轉義的效果邮丰,代表后面接的字符有特殊含義
- 所以使其表示反斜杠應寫成\\(雙反斜杠,第一個用作轉義)
re.findall('\\', 'abc\123') # 執(zhí)行會報錯
- 代碼在正則下匹配是正確的铭乾,但是執(zhí)行代碼剪廉,程序會報錯
- 原因:
- 雖然正則表示的寫法是正確的,但是程序是運行在python下的
- 在python代碼中炕檩,我們寫的是\\(雙反斜杠)表示反斜杠斗蒋,這只是在python代碼中
- 當python代碼傳遞過去給正則表達式,其實是一條反斜杠的轉義符,但是正確的表達式需要2條泉沾,所以python代碼需要寫成4條反斜杠才能匹配成功
- 修改代碼后為:
re.findall('\\\\', 'abc\123') # ok
-
原生字符串r的產(chǎn)生
- 通過上面的寫法骤星,會很麻煩,于是就產(chǎn)生了遠程字符串的概念
ret = re.findall(r'\\', r'abc\123') # ['\\']其中一個是轉義爆哑,表示一個反斜杠
- 代碼中,r表示后面字符串的內(nèi)容就是代表反斜杠舆吮,沒有別的意思揭朝,代碼執(zhí)行的時候,python把2個反斜杠原封不動的傳給正則色冀,正則拿到反斜杠潭袱,第一個用作第二個的轉義
- 這樣代碼執(zhí)行的時候會更加直觀
執(zhí)行下面代碼
ret = re.findall('\\d', 'w3t5e7') print(ret) ret = re.findall(r'\d', 'w3t5e7') print(ret) ret = re.findall('\d', 'w3t5e7') print(ret) ======== ['3', '5', '7'] ['3', '5', '7'] ['3', '5', '7']
- 原因:
- 第一個傳入兩個反斜杠,python轉義之后锋恬,傳到正則后是一個反斜杠
- 一個反斜杠轉義d屯换,表示數(shù)字
- 第二個通過r指定反斜杠是原生字符串,反斜杠直接傳到正則表達式轉義d
- 第三個理論上會報錯与学,但是反斜杠d在ascii碼表上沒有特殊含義彤悔,python內(nèi)部會將其原封不動傳給正則表達式,但是如果遇到時\a之類的就報錯了
- 所以嚴格來說按12的寫才是正確的
-
findall用法
- findall優(yōu)先把組里的內(nèi)容取出來
regex = 'www.(baidu|youku).com' ret = re.findall(regex, 'www.baidu.com') print(ret) # ['baidu']
- 如果要去掉優(yōu)先捕獲
regex = 'www.(?:baidu|youku).com' ret = re.findall(regex, 'www.baidu.com') print(ret) # ['www.baidu.com']