目錄
[1鞭呕、 什么是正則表達(dá)式.
[2、 正則表達(dá)式語(yǔ)法結(jié)構(gòu).
[2.1. 入門案例:了解正則表達(dá)式.
[2.3. python中的正則表達(dá)式模塊re
[2.3.1 字符串查詢匹配的函數(shù):
[2.3.2 字符串拆分替換的函數(shù):
[2.4. 正則表達(dá)式中的元字符.
[2.5. 正則表達(dá)式中的量詞.
[2.6. 正則表達(dá)式中的范圍匹配.
[2.7. 正則表達(dá)式中的分組.
[2.8. 正則表達(dá)式中的特殊用法.
[2.9 正則表達(dá)式的貪婪模式和懶惰模式.
1.什么是正則表達(dá)式
正則表達(dá)式:也稱為規(guī)則表達(dá)式,英文名稱Regular Expression, 我們?cè)诔绦蛑薪?jīng)常會(huì)縮寫為 regex 或者 regexp, 專門用于進(jìn)行文本檢索、匹配、替換等操作的一種技術(shù)惜论,
注意:正則表達(dá)式是一種獨(dú)立的技術(shù),并不是某編程語(yǔ)言獨(dú)有的
正則表達(dá)式止喷,是一種特殊的符號(hào)馆类,這樣的符號(hào)是需要解釋才能使用的,也就是需要正則表達(dá)式引擎來(lái)進(jìn)行解釋弹谁,目前正則表達(dá)式的引擎主要分三種:DFA,NFA,POSIX NFA/ 有興趣了解正則表達(dá)式引擎的童鞋乾巧,可以自己查看資料。
2.正則表達(dá)式語(yǔ)法結(jié)構(gòu)
接下來(lái)预愤,我們開始了解這樣一個(gè)神秘的可以類似人類神經(jīng)網(wǎng)絡(luò)一樣思考問(wèn)題的技術(shù)的語(yǔ)法結(jié)構(gòu)
注意:我們通過(guò)python程序進(jìn)行測(cè)試沟于,但是正則表達(dá)式的語(yǔ)法結(jié)構(gòu)在各種語(yǔ)言環(huán)境中都是通用的。
2.1入門案例:了解正則表達(dá)式
我們通過(guò)一個(gè)簡(jiǎn)單的案例入手:通常情況下植康,我們會(huì)驗(yàn)證用戶輸入的手機(jī)號(hào)碼是否合法旷太,是否 156/186/188開頭的手機(jī)號(hào)碼,如果按照常規(guī)驗(yàn)證手段,就需要對(duì)字符串進(jìn)行拆分處理供璧,然后逐步匹配
重要提示:python中提供了re模塊存崖,包含了正則表達(dá)式的所有功能,專門用于進(jìn)行正則表達(dá)式的處理睡毒;
案例:
def validatephone(phone):
#定義正則表達(dá)式来惧,python中的正則表達(dá)式還是一個(gè)字符串,是以 r 開頭的字符串
regexp = r"^(156|186|188)\d{8}$"
#開始驗(yàn)證
if re.match(regexp,phone):
return "手機(jī)號(hào)碼合法”
else:
return "手機(jī)號(hào)碼只能以156/186/188開頭演顾,并且每一個(gè)字符都是數(shù)字供搀,請(qǐng)檢查"
#開始驗(yàn)證
print(validatephone(userphone))
執(zhí)行上面的代碼,我們得到正常驗(yàn)證的結(jié)果钠至,大家可以自己試一試趁曼,
使用正則表達(dá)式之后會(huì)使程序變得非常簡(jiǎn)潔,接下里棕洋,我們繼續(xù)正則表達(dá)式的表演
2.3python中的正則表達(dá)式模塊re
2.3.1字符串查詢匹配的函數(shù):
函數(shù) 描述
re ,match(reg, info) 用于在開始位置匹配目標(biāo)字符串info中符合正則表達(dá)式reg的字符,匹配成功會(huì)返回一個(gè)match對(duì)象乒融,匹配不成功返回None
re, search(reg,info) 掃描整個(gè)字符串info掰盘,使用正則表達(dá)式reg進(jìn)行匹配,匹配成功返回匹配的第一個(gè)match對(duì)象赞季,匹配不成功返回None
re,findall(reg,info) 掃描整個(gè)字符串info愧捕,將符合整個(gè)表達(dá)式reg的字符全部提取出來(lái)存放在列表中返回
re , fullmatch(reg,info) 掃描整個(gè)字符串,如果整個(gè)字符串都包含在正則表達(dá)式表示的范圍中申钩,返回整個(gè)字符串次绘,否則返回None
re, finditer(reg,info) 掃描整個(gè)字符串,將匹配到的字符保存在一個(gè)可以遍歷的列表中
參考官方re.py源代碼如下:
2.3.2字符串拆分替換的函數(shù):
函數(shù) 描述
re.split(reg,string) 使用指定的正則表達(dá)式reg匹配的字符撒遣,將字符串string 拆分成一個(gè)字符串列表邮偎,如:re.split(r."\s+",info),表示使用一個(gè)或者多個(gè)空白字符對(duì)字符串info進(jìn)行拆分,并返回一個(gè)拆分后的字符串列表
re,sub(reg,repl,string) 只用指定的字符串repl來(lái)替換字符串string中匹配正則表達(dá)式reg的字符
接下來(lái)义黎,我們進(jìn)入正則表達(dá)式干貨部分
2.4正則表達(dá)式中的元字符
在使用正則表達(dá)式的過(guò)程中禾进,一些包含特殊含義的字符,用于表示字符串中一些特殊的位置非常重要廉涕,我們先簡(jiǎn)單了解一下一些常用的元字符
元字符 描述
^ 表示匹配字符串的開頭位置的字符
$ 表示匹配字符串的結(jié)束位置的字符
. 表示匹配任意一個(gè)字符
\d 匹配一個(gè)數(shù)字字符
\D 匹配一個(gè)非數(shù)字字符
\s 匹配一個(gè)空白字符
\S 匹配一個(gè)非空白字符
\w 匹配一個(gè)數(shù)字/字母/下劃線中任意一個(gè)字符
\W 匹配一個(gè)非數(shù)字字母下劃線的任意一個(gè)字符
\b 匹配一個(gè)單詞的邊界
\B 匹配不是單詞的開頭或者結(jié)束位置
上干貨:代碼案例
導(dǎo)入正則表達(dá)式模塊
import re
#定義測(cè)試文本字符串泻云,我們后續(xù)再這段文本中查詢數(shù)據(jù)
msg1 = '''pyhton is an easy to learn, powerful programming language.
it has efficient high-level data structures and a simple but effective approach to object-oriented programming.
python'selegant syntax and dynamic typing,together with its interpreted nature,
make it an ideal language for scripting and rapid application development in many areas on most platforms.
'''
msg2 = 'hello'
msg3 = 'hello%'
#定義正則表達(dá)式,匹配字符串開頭是否為pyhton
regStart = r"efficient"
#從字符串開始位置匹配狐蜕,是否包含符合正則表達(dá)式的內(nèi)容宠纯,返回匹配到的字符串的match對(duì)象
print(re.match(regStart,msg1))
#掃描整個(gè)字符串,是否包含符合正則表達(dá)式的內(nèi)容层释,返回匹配到的第一個(gè)字符串的match對(duì)象
print(re.search(regStart,msg1))
#掃描整個(gè)字符串婆瓜,是否包含符合正則表達(dá)式的內(nèi)容,返回匹配到的所有字符串列表
print(re,findall(regStart,msg1))
#掃描整個(gè)字符串湃累,是否包含符合正則表達(dá)式的內(nèi)容太勃救,返回匹配到的字符串的迭代對(duì)象
for r in re.finditer(regStart ,msg1):
print("->"+ r.group())
#掃描整個(gè)字符串碍讨,是否包含在正則表達(dá)式匹配到的內(nèi)容中,是則返回整個(gè)字符串蒙秒,否則返回None
print(re.fullmatch(r"\w*",msg2))
print(re,fullmatch(r"\w*",msg3))
上述代碼執(zhí)行結(jié)果如下:
None
<sre.SRE_MATCH object;span=(66,75)match = 'efficient'>
['efficient']
->efficient
<sre.SRE_Match object; span = (0,5),match = 'hello'>
None
2.5正則表達(dá)式中的量詞
正則表達(dá)式中的量詞勃黍,是用于限定數(shù)量的特殊字符
量詞 描述
x* 用于匹配符號(hào)*前面的字符出現(xiàn)0次或者多次
x+ 用于匹配符號(hào)+前面的字符出現(xiàn)1次或者多次
x? 用于匹配符號(hào)?前面的字符出現(xiàn)0次或者1次
x{n} 用于匹配符號(hào){n}前面的字符出現(xiàn)n次
x{m,n} 用于匹配符號(hào){m,n}前面的字符出現(xiàn)至少m次晕讲,最多n次
x{n,} 用于匹配符號(hào){n,}前面的字符出現(xiàn)至少n次
接著上代碼干貨:
2.6.正則表達(dá)式中的范圍匹配
在正則表達(dá)式中覆获,針對(duì)字符的匹配,出了快捷的元字符的匹配瓢省,還有另一種使用方括號(hào)進(jìn)行的范圍匹配方式弄息,具體如下:
范圍 描述
[0-9] 用于匹配一個(gè)0~9之間的數(shù)字,等價(jià)于\d
[^0-9] 用于匹配一個(gè)非數(shù)字字符勤婚,等價(jià)于\D
[3-6] 用于匹配一個(gè)3~6之間的數(shù)字
[a-z] 用于匹配一個(gè)a~z之間的字母
[A-Z] 用于匹配一個(gè)A~Z之間的字母
[a-f] 用于匹配一個(gè)a~f之間的字母
[a-zA-Z] 用于匹配一個(gè)a~z或者A-Z之間的字母摹量,匹配任意一個(gè)字母
[a-zA-Z0-9] 用于匹配一個(gè)字母或者數(shù)字
[a-zA-Z0-9_] 用于匹配一個(gè)字母或者數(shù)字或者下劃線,等價(jià)于\w
[^a-zA-Z0-9_] 用于匹配一個(gè)非字母或者數(shù)字或者下劃線馒胆,等價(jià)于\W
注意:不要使用【0-120】來(lái)表示0~120之間的數(shù)字缨称,這是錯(cuò)誤的,整理測(cè)試代碼如下:
2.7.正則表達(dá)式中的分組
正則表達(dá)式主要是用于進(jìn)行字符串檢索匹配操作的利器祝迂,在一次完整的匹配過(guò)程中睦尽,可以將匹配到的結(jié)果進(jìn)行分組,這樣就更加的細(xì)化了我們隊(duì)匹配結(jié)果的操作
正則表達(dá)式通過(guò)圓括號(hào)()進(jìn)行分組型雳,以提取匹配結(jié)果的部分結(jié)果
常用的兩種分組
分組 描述
(expression) 使用圓括號(hào)直接分組当凡;正則表達(dá)式本身匹配的結(jié)果就是一個(gè)組,可以通過(guò)group()或者group(0)獲染兰蟆沿量;然后正則表達(dá)式中包含的圓括號(hào)就是按照順序從1開始編號(hào)的小組
(?P<name>expression) 使用圓括號(hào)分組冤荆,然后給當(dāng)前的圓括號(hào)表示的小組命名為name欧瘪,可以通過(guò)group(name) 進(jìn)行數(shù)據(jù)的獲取
2.8.正則表達(dá)式中的特殊用法
使用分組的同,會(huì)有一些特殊的使用方式如下:
2.9正則表達(dá)式的貪婪模式和懶惰模式
在某些情況下匙赞,我們匹配的字符串出現(xiàn)一些特殊的規(guī)律是佛掖,就會(huì)出現(xiàn)匹配結(jié)果不盡如人意的意外情況
如:在下面的字符串中,將div標(biāo)簽中的所有內(nèi)容獲取出來(lái)
如:在下面的字符串中涌庭,將div標(biāo)簽中的所有內(nèi)容獲取出來(lái)
<div>內(nèi)容1</div><p>這本來(lái)是不需要的內(nèi)容</p><div>內(nèi)容2</div>
此時(shí)芥被,我們想到的是,使用<div>作為關(guān)鍵信息進(jìn)行正則表達(dá)式的定義坐榆,如下
regexp = r"<div>.*</div>"
本意是使用上述代碼來(lái)完成div開始標(biāo)簽和結(jié)束標(biāo)簽之間的內(nèi)容匹配拴魄,但是,匹配的結(jié)果如下
<div> [內(nèi)容1</div><p>這本來(lái)是不需要的內(nèi)容</p><div>內(nèi)容2] </div>
我們可以看到,上面匹配的結(jié)果匹中,是將字符串開頭的<div>標(biāo)簽和字符串結(jié)束的</div>當(dāng)成了匹配元素疚宇,對(duì)包含在中間的內(nèi)容直接進(jìn)行了匹配仆邓,也就得到了我們期望之外的結(jié)果:
內(nèi)容1</div><p>這本來(lái)是不需要的內(nèi)容</p><div>內(nèi)容2
上述就是我們要說(shuō)的正則表達(dá)式的第一種模式:貪婪模式
貪婪模式:正則表達(dá)式匹配的一種模式,速度快,但是匹配的內(nèi)容會(huì)從字符串兩頭向中間搜索匹配(比較貪婪~)思劳,一旦匹配選中盈罐,就不繼續(xù)向字符串中間搜索了媒殉,過(guò)程如下:
開始:<div>內(nèi)容1</div><p>這本來(lái)是不需要的內(nèi)容</p><div>內(nèi)容2</div>
第一次匹配:【<div>內(nèi)容1</div><p>這本來(lái)是不需要的內(nèi)容</p><div>內(nèi)容2</div>】
第二次匹配<div>【內(nèi)容1</div><p>這本來(lái)是不需要的內(nèi)容</p><div>內(nèi)容2】</div>
匹配到正則中需要的結(jié)果梁沧,不再繼續(xù)匹配,直接返回匹配結(jié)果如下:
內(nèi)容1</div><p>這本來(lái)是不需要的內(nèi)容</p><div>內(nèi)容2
明顯貪婪模式某些情況下重虑,不是我們想要的践付,所以出現(xiàn)了另一種模式:懶惰模式
懶惰模式:正則表達(dá)式匹配的另一種模式,會(huì)首先搜索匹配正則表達(dá)式開始位置的字符缺厉,然后逐步向字符串的結(jié)束位置查找永高,一旦找到匹配的就返回,然后接著查找
regexp = r"<div>.*?</div>"
開始:<div>內(nèi)容1</div><p>這本來(lái)是不需要的內(nèi)容</p><div>內(nèi)容2</div>
第一次匹配:【<div>】?jī)?nèi)容1</div><p>這本來(lái)是不需要的內(nèi)容</p><div>內(nèi)容2</div>
第二次匹配【<div>內(nèi)容1</div>】<p>這本來(lái)是不需要的內(nèi)容</p><div>內(nèi)容2</div>
匹配到正則中需要的結(jié)果:內(nèi)容1
繼續(xù)向后查找
第三次匹配<div>內(nèi)容1</div>【<p>這本來(lái)是不需要的內(nèi)容</p>】<div>內(nèi)容2</div>
第四次匹配<div>內(nèi)容1</div><p>這本來(lái)是不需要的內(nèi)容</p>【<div>內(nèi)容2</div>】
匹配到正則中需要的結(jié)果:內(nèi)容2
查找字符串結(jié)束提针!
正則表達(dá)式匹配的兩種模式:貪婪模式乏梁、懶惰模式
貪婪模式:從目標(biāo)字符串的兩頭開始搜索,一次盡可能多的匹配符合條件的字符串关贵,但是有可能會(huì)匹配到不需要的內(nèi)容,正則表達(dá)式中的元字符卖毁、量詞揖曾、范圍等都模式是貪婪匹配模式,使用的時(shí)候一定要注意分析結(jié)果亥啦,如:<div>.</div>就是一個(gè)貪婪模式炭剪,用于匹配<div>和</div>之間所有的字符
懶惰模式:從目標(biāo)字符串按照順序從頭到位進(jìn)行檢索匹配,盡可能的檢索到最小范圍的匹配結(jié)果翔脱,語(yǔ)法結(jié)構(gòu)是在貪婪模式的表達(dá)式后面加上一個(gè)符號(hào)?即可奴拦,如<div>.?</div>就是一個(gè)懶惰模式的正則,用于僅僅匹配最小范圍的<div>和</div>之間的內(nèi)容
不論貪婪模式還是懶惰模式届吁,都有適合自己使用的地方错妖,大家一定要根據(jù)實(shí)際需求進(jìn)行解決方案的確定