Python入門課程系列:
- Python學(xué)習(xí) day1:認(rèn)識(shí)Python
- Python學(xué)習(xí) day2:判斷語(yǔ)句與循環(huán)控制
- Python學(xué)習(xí) day3:高級(jí)數(shù)據(jù)類型
- Python學(xué)習(xí) day4:函數(shù)基礎(chǔ)
- Python學(xué)習(xí) day5:函數(shù)
- Python學(xué)習(xí) day6:內(nèi)置函數(shù)
- Python學(xué)習(xí) day7:面向?qū)ο蠡A(chǔ)·上
- Python學(xué)習(xí) day8:面向?qū)ο蠡A(chǔ)·中
- Python學(xué)習(xí) day9:面向?qū)ο蠡A(chǔ)·下
- Python學(xué)習(xí) day10:飛機(jī)大戰(zhàn)游戲
- Python學(xué)習(xí) day11:文件操作與模塊
- Python學(xué)習(xí) day12:Python垃圾回收機(jī)制
導(dǎo)入:正則表達(dá)式是對(duì)字符串操作的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個(gè)"規(guī)則字符串"翻屈,這個(gè)"規(guī)則字符串"用來表達(dá)對(duì)字符串的一種過濾邏輯。
目錄:
- 概述
- re模塊
- 貪婪模式與非貪婪模式
目標(biāo):
- 區(qū)分正則表達(dá)式和python正則表達(dá)式的相同點(diǎn)和不同點(diǎn)
- 使用re模塊的相關(guān)方法處理數(shù)據(jù)(重點(diǎn)本橙、難點(diǎn))
- 區(qū)分貪婪模式與非貪婪模式,使用非貪婪模式解決特殊的數(shù)據(jù)處理問題(難點(diǎn))
1. 概述
正則表達(dá)式,英文名為Regular Expression宠纯,又稱規(guī)則表達(dá)式。正則表達(dá)式通常被用來檢索层释、替換那些符合某個(gè)模式(規(guī)則)的文本婆瓜。
在主流操作系統(tǒng)(Linux、Unix贡羔、Windows廉白、HP、BeOS等)乖寒、主流的開發(fā)語(yǔ)言(delphi猴蹂、Scala、PHP楣嘁、C#晕讲、Java、C++马澈、Objective-c、Swift弄息、VB痊班、Javascript、Ruby以及Python等)摹量、數(shù)以億萬(wàn)計(jì)的各種應(yīng)用軟件中涤伐,都可以看到正則表達(dá)式的身影馒胆。
Python自1.5版本起增加了re模塊,它提供Perl風(fēng)格的正則表達(dá)式模式凝果。re模塊使Python語(yǔ)言擁有全部的正則表達(dá)式功能祝迂。同時(shí)re模塊是用c語(yǔ)言寫的,其匹配速度非称骶唬快型雳。
其中compile函數(shù)根據(jù)一個(gè)模式字符串和可選的標(biāo)志參數(shù)生成一個(gè)正則表達(dá)式對(duì)象。該對(duì)象擁有一系列方法用于正則表達(dá)式匹配和替換山害。re模塊也提供了與這些方法功能完全一致的函數(shù)纠俭,這些函數(shù)使用一個(gè)模式字符串作為它們的第一個(gè)參數(shù)。
2. re模塊
目的:通過python中re模塊的使用最終掌握正則表達(dá)式的常用匹配規(guī)則
一:常用方法
1)re.match方法
re.match嘗試從字符串的起始位置匹配一個(gè)規(guī)則浪慌,匹配成功就返回match對(duì)象冤荆,否則返回None∪ㄏ耍可以使用group()獲取匹配成功的字符串钓简。
- 語(yǔ)法 :re.match(pattern, string,flags=0)
- 參數(shù)說明:
參數(shù) | 描述 |
---|---|
pattern | 匹配的正則表達(dá)式 |
string | 要匹配的字符串 |
flags | 標(biāo)志位,用于控制正則表達(dá)式的匹配方式汹想。如:是否區(qū)分大小寫外邓,多行匹配等 |
import re
str='Python is the best language in the world'
#match只能匹配以xxx開頭的字符串,第一個(gè)參數(shù)是正則欧宜,第二個(gè)參數(shù)是要匹配的字符串
res=re.match('Python',str) #精確匹配
print(res)
print(res.group()) #匹配成功使用group方法取出字符串
#<re.Match object; span=(0, 6), match='Python'>
#Python
res=re.match('y',str) #只匹配開頭坐榆,匹配不到y(tǒng),會(huì)報(bào)錯(cuò)
print(res) #匹配失敗是沒有g(shù)roup函數(shù)的
#None
- 標(biāo)志位:
如果同時(shí)使用多個(gè)標(biāo)志位冗茸,使用|分割席镀。如re.L|re.M
修飾符 | 描述 |
---|---|
re.I | 使匹配對(duì)大小寫不敏感 |
re.L | 做本地化識(shí)別(locale-aware)匹配 |
re.M | 多行匹配,影響^和$ |
re.S | 使用.來匹配包括換行在內(nèi)的所有字符 |
re.U | 根據(jù)Unicode字符解析字符夏漱。這個(gè)標(biāo)志影響\w豪诲,\W,\b挂绰,\B |
re.X | 該標(biāo)志通過給予你更靈活的格式以便你將正則表達(dá)式寫的更易于理解 |
import re
str='Python is the best language in the world'
res=re.match('python',str,re.I) #忽略大小寫
print(res.group())
#Python
- 我們可以使用group(num)或groups()匹配對(duì)象函數(shù)來獲取匹配表達(dá)式
匹配對(duì)象方法 | 描述 |
---|---|
group() | 匹配整個(gè)表達(dá)式的字符串屎篱,如果匹配到多個(gè)結(jié)果將返回一個(gè)包含那些組所對(duì)應(yīng)的元組】伲可以通過下標(biāo)獲取返回的結(jié)果交播。 |
groups() | 返回一個(gè)包含所有小組字符串的元組,從1到包含的小組號(hào)践付。不支持用下標(biāo)取 |
import re
str='Python is the best language in the world'
res=re.match('(.*) is (.*?) .*',str) #忽略大小寫
print(res)
print(res.group())
#<re.Match object; span=(0, 40), match='Python is the best language in the world'>
#Python is the best language in the world
print(res.group(1))
print(res.group(2))
#Python
#the
print(res.groups())
#('Python', 'the')
2)re.compile方法
compile可以將正則表達(dá)式模式編譯成一個(gè)正則表達(dá)式對(duì)象
- reg = re.compile(pattern)result = reg.match(string)
- 等效于 result = re.match(pattern, string)
- 使用re.compile()和保存所產(chǎn)生的正則表達(dá)式對(duì)象可以增加重用效率
優(yōu)點(diǎn):在使用正則表達(dá)式進(jìn)行match操作時(shí)秦士,python會(huì)將字符串轉(zhuǎn)換為正則表達(dá)式對(duì)象。如果使用compile永高,只需要一次轉(zhuǎn)換即可隧土。以后再使用模式對(duì)象的話提针,無需重復(fù)轉(zhuǎn)換。
import re
reobj=re.compile('\d{4}')
print(reobj.match('56789345').group())
#5678
3)re.search方法
search在全文中匹配一次曹傀,匹配到就返回
- 語(yǔ)法:re.search(pattern, string,flag=0)
- 函數(shù)參數(shù)說明
參數(shù) | 描述 |
---|---|
pattern | 匹配的正則表達(dá)式 |
string | 要匹配的字符串 |
flags | 標(biāo)志位辐脖,用于控制正則表達(dá)式的匹配方式。如:是否區(qū)分大小寫皆愉,多行匹配等等 |
import re
data='我愛偉大的祖國(guó)嗜价,I love China, China is a great country'
rs=re.search('China',data)
print(rs)
#<re.Match object; span=(15, 20), match='China'>
print(rs.group())
#China
data='華為是華人華僑的驕傲'
rs=re.search('華.',data)
print(rs.group())
#華為
reobj=re.compile('華.')
print(reobj.search(data).group())
#華為
4)re.findall方法
findall匹配字符串中某個(gè)正則表達(dá)式全部的非重復(fù)出現(xiàn)的情況,返回一個(gè)列表亥啦。這個(gè)方法使用頻率較高炭剪。(在爬蟲中非常實(shí)用)
- 語(yǔ)法:re.findall(string[,pos[,endpos]])
- 函數(shù)參數(shù)說明
參數(shù) | 描述 |
---|---|
string | 待匹配的字符串 |
pos | 可選參數(shù),指定字符串的起始位置翔脱,默認(rèn)是0奴拦。 |
endpos | 可選參數(shù),指定字符串的結(jié)束位置届吁,默認(rèn)為字符串的長(zhǎng)度错妖。 |
import re
data='華為是華人華僑的驕傲'
rs=re.findall('華.',data)
print(rs)
# ['華為', '華人', '華僑']
reobj=re.compile('華.')
print(reobj.findall(data))
#['華為', '華人', '華僑']
5)re.sub方法 / re.subn方法
re.sub將匹配到的數(shù)據(jù)進(jìn)行替換
- 語(yǔ)法:sub(pattern,repl,string,count=0,flags=0)
- 函數(shù)參數(shù)說明
參數(shù) | 描述 |
---|---|
pattern | 正則中的模式字符串 |
repl | 替換的字符串,也可為一個(gè)函數(shù) |
string | 要被查找替換的原始字符串 |
count | 模式匹配后替換的最大次數(shù)疚沐,默認(rèn)0表示替換所有的匹配 |
flags | 標(biāo)志位暂氯,用于控制正則表達(dá)式的匹配方式 |
import re
ret=re.sub('h','H','hello hero')
print(ret)
#Hello Hero
import re
dataS='Python是很受歡迎的語(yǔ)言'
pattern='[a-zA-Z]+'
res=re.sub(pattern,'R',dataS)
print(res)
#R是很受歡迎的語(yǔ)言
re.subn 完成目標(biāo)的搜索和替換,以元組的形式返回被替換的數(shù)量
import re
dataS='Python是很受歡迎的語(yǔ)言Python'
pattern='[a-zA-Z]+'
res=re.subn(pattern,'R',dataS)
print(res)
#('R是很受歡迎的語(yǔ)言R', 2)
6)re.split方法
re.split根據(jù)匹配進(jìn)行字符串切割亮蛔,并返回一個(gè)列表
- 語(yǔ)法:split(pattern,string,maxsplit=0,flags=0)
- 函數(shù)參數(shù)說明
參數(shù) | 描述 |
---|---|
pattern | 匹配的正則表達(dá)式 |
string | 要被查找替換的原始字符串 |
maxsplit | 分隔次數(shù)痴施,maxsplit=1分隔一次,默認(rèn)為0究流,不限制次數(shù)辣吃。 |
flags | 標(biāo)志位,用于控制正則表達(dá)式的匹配方式 |
import re
data='百度,騰信,阿里,華為,360'
print(re.split(',',data))
#['百度', '騰信', '阿里', '華為', '360']
二:常用匹配規(guī)格
1)常用匹配規(guī)則-匹配字符
符號(hào) | 匹配規(guī)則 |
---|---|
. | 匹配任意1個(gè)字符除了換行符\n(不匹配非字符) |
[abc] | 匹配abc中任意一個(gè)字符 |
\d | 匹配一個(gè)數(shù)字(0-9) |
\D | 匹配一個(gè)非數(shù)字芬探,即不是數(shù)字 |
\s | 匹配一個(gè)空白字符神得,即空格,tab鍵 |
\S | 匹配一個(gè)非空白字符偷仿,即除空格哩簿,tab鍵之外的內(nèi)容 |
\w | 匹配任意單個(gè)字母、數(shù)字或下劃線酝静,即a-z节榜、A-Z、0-9别智、_ |
\W | 匹配\w之外的任意單個(gè)字符 |
- .的使用:
#例1
import re
data='a1aaa'
pattern='.' #將.定義為變量pattern
res=re.match(pattern,data)
print(res.group())
#a
pattern='...'
res=re.match(pattern,data)
print(res.group())
#a1a
#例2
import re
names=('李清照','李牧','賀知章','王維')
pattern='李.'
for name in names:
res = re.match(pattern, name)
if res:
print(res.group())
#李清
#李牧
- []的使用:
使用[]括起來的內(nèi)容全跨,代表一個(gè)集合,代表匹配集合內(nèi)的人一個(gè)字符亿遂。[abc]代表可以匹配a或者b或者c
#例1
import re
str1='hello'
res=re.match('[he]',str1)
print(res.group())
#h
res=re.match('[mh]',str1)
print(res.group())
#h
#例2
import re
datas='a','b','d','aeiou'
pattern='[a-c]' #范圍可以簡(jiǎn)寫
for data in datas:
res = re.match(pattern, data)
if res:
print(res.group())
#a
#b
#a
- \d和\D的使用:
import re
data='12345aeiou'
print(re.match('\d',data).group())
#1
print(re.match('\d\d',data).group())
#12
print(re.match('\d*4',data).group())
#1234
data='w12345aeiou'
print(re.match('\D',data).group())
#w
- \s和\S的使用:
import re
data=' hello'
print(re.match('\s',data).group())
# #返回一個(gè)空白字符
data='! hello'
print(re.match('\S',data).group())
#!
- \w和\W的使用:
import re
data='ssdf'
print(re.match('\w',data).group())
#s
data='!hello'
print(re.match('\W',data).group())
#!
2)常用匹配規(guī)則-匹配字符數(shù)量
符號(hào) | 匹配規(guī)則 |
---|---|
* | 匹配前一個(gè)字符出現(xiàn)0次或者無限次浓若,即可有可無。相當(dāng)于{0,} |
+ | 匹配前一個(gè)字符出現(xiàn)1次或者無限次蛇数,即至少有1次挪钓。相當(dāng)于{1,} |
? | 匹配前一個(gè)字符出現(xiàn)1次或0次,即要么有1次耳舅,要么沒有碌上。相當(dāng)于{0,1} |
{m} | 匹配前一個(gè)字符出現(xiàn)m次 |
{m,} | 匹配前一個(gè)字符至少出現(xiàn)m次 |
{n,m} | 匹配前一個(gè)字符出現(xiàn)從n到m次 |
- *的使用
import re
print(re.match('[A-Z][a-z]*','MYName').group())
#M #*前面的沒有也可以
print(re.match('[A-Z]*','MMMy').group())
#MMM
print(re.match('[A-Z][a-z]*','MyyyyyyName').group())
#Myyyyyy
- +的使用實(shí)例:
import re
print(re.match('[A-Z][a-z]+','Mame').group())
#M #*前面至少有一個(gè),否則會(huì)報(bào)錯(cuò)浦徊。
print(re.match('[A-Z]+','MMMy').group())
#MMM
print(re.match('[A-Z][a-z]+','MyyyyyyName').group())
#Myyyyyy
??寫一個(gè)正則匹配python變量名(變量名語(yǔ)法規(guī)則:不能以數(shù)字開頭馏予,變量名只能包含字母,數(shù)字盔性,下劃線)
import re
print(re.match('[a-zA-Z_]+[\w]*','name').group())
#name
print(re.match('[a-zA-Z_]+[\w]*','_name').group())
#_name
print(re.match('[a-zA-Z_]+[\w]*','_name333').group())
#_name333
- \ ?的使用實(shí)例:(\是轉(zhuǎn)義符)
import re
print(re.match('[a-zA-Z_][0-9]?','n3ame').group())
#n3
print(re.match('[a-zA-Z_][0-9]?','name').group())
#n
- {}的使用:
{count}:精確匹配
{min, max}:告訴引擎匹配前導(dǎo)字符min次到max次霞丧。min和max必須都是非負(fù)整數(shù)。
if result:
print('匹配成功{}'.format(result.group()))
#匹配成功1234
result=re.match('\d{4,}','123456789')
if result:
print('匹配成功{}'.format(result.group()))
#匹配成功123456789
result=re.match('\d{4,6}','123456789')
if result:
print('匹配成功{}'.format(result.group()))
#匹配成功123456
匹配郵箱 格式:xxx @163.com
import re
checkMail=input('請(qǐng)輸入您的163郵箱:')
regexMail=re.match('[a-zA-Z1-9]+[a-zA-Z0-9]{6,11}'+'@163.com',checkMail)
if regexMail:
print('匹配成功{}'.format(regexMail.group()))
3)常用匹配規(guī)則-原生字符串
python字符串中\(zhòng)作為轉(zhuǎn)義字符開頭冕香,比如\n表示換行蛹尝,\t表示tab鍵,為了表示\本身悉尾,再加上一個(gè)\突那,去對(duì)\進(jìn)行轉(zhuǎn)義,成為 \ \ 形式构眯。也就是\ \ 的寫法才能表示\本身愕难。
import re
mypath='‘G:\py資料\1-上課資料\4-正則表達(dá)式\html'
print(mypath)
#‘G:\py資料?-上課資料?-正則表達(dá)式\html
import re
mypath='‘G:\\py資料\\1-上課資料\\4-正則表達(dá)式\\html'
print(mypath)
#‘G:\py資料\1-上課資料\4-正則表達(dá)式\html
- 使用正則表達(dá)式來匹配路徑
正則中\(zhòng)也表示轉(zhuǎn)義,所以要匹配字符串中的\需要再次轉(zhuǎn)義惫霸。
如果不想轉(zhuǎn)義猫缭,可以在正則前面加上字符r,表示原生的字符串它褪,python字符串就不再轉(zhuǎn)義饵骨。
import re
print(re.match('c:\\a.txt','c:\\a.txt').group())
#AttributeError: 'NoneType' object has no attribute 'group'
print(re.match('c:\\\\a.txt','c:\\a.txt').group())
#c:\a.txt
print(re.match(r'c:\\a.txt','c:\\a.txt').group())
#c:\a.txt
4)常用匹配規(guī)則-匹配開頭結(jié)尾
符號(hào) | 匹配規(guī)則 |
---|---|
^ | 匹配字符串開頭 |
$ | 匹配字符串結(jié)尾 |
import re
print(re.match('^p.*','python is a language').group())
#python is a language
print(re.match('^p\w{5}','python is a language').group())
#python
print(re.match('\w{5,15}@[\w]{3}.com$','python@163.com').group())
??^除了有匹配開頭的意思,還可以取反
如[^xyz]就是取非xyz的意思
5)常用匹配規(guī)則-分組匹配
符號(hào) | 匹配規(guī)則 |
---|---|
| | 匹配左右任意一個(gè)表達(dá)式 |
(ab) | 將括號(hào)中字符作為一個(gè)分組 |
\num | 引用分組num匹配到的字符串 |
(?P) | 分組起別名 |
(?P=name) | 引用別名為name分組匹配到的字符串 |
- |的使用
|實(shí)際上是一個(gè)或的關(guān)系茫打,先匹配|前面的居触,匹配到了之后就不再匹配|后面的內(nèi)容
import re
print(re.match('[1-9]?\d$|100','78').group())
#78
print(re.match('[1-9]?\d$|100','100').group())
#100
string='wehvjcgvg888'
print(re.match('(wehvjcgvg|wehvjcgvg888)',string).group())
#wehvjcgvg |實(shí)際上是一個(gè)或的關(guān)系,先匹配|前面的老赤,匹配到了之后就不再匹配|后面的
- (ab)的使用
import re
res=re.match('([0-9]*)-(\d*)','0355-348798856')
print(res.group(0))
print(res.group(1))
print(res.group(2))
# 0355-348798856
# 0355
# 348798856
- (\num)的使用:
在匹配的過程中轮洋,可以在后面引用前面分組num匹配到的字符串
import re
htmlTag='<html><h1>測(cè)試數(shù)據(jù)</h1></html>'
res=re.match(r'<(.+)><(.+)>.+<(/\2)></\1>',htmlTag)
print(res.group())
print(res.group(1))
print(res.group(2))
print(res.group(3))
# <html><h1>測(cè)試數(shù)據(jù)</h1></html>
# html
# h1
# /h1
但在使用組引用的時(shí)候如果有很多組就容易引起混亂,也不方便閱讀抬旺。
為了解決這個(gè)問題可以給分組起別名
語(yǔ)法:
起別名:(?P<name>)
使用別名:(?P=name)
data='<div><h1>www.daibu.com</h1></div>'
ret=re.match(r'<(\w*)><(\w*)>.*<(/\w*)></\w*>',data)
print(ret.group())
#<div><h1>www.daibu.com</h1></div>
ret=re.match(r'<(?P<div>\w*)><(?P<h1>\w*)>.*</(?P=h1)></(?P=div)>',data)
print(ret.group())
#<div><h1>www.daibu.com</h1></div>
3. 貪婪模式與非貪婪模式
Python里數(shù)量詞默認(rèn)是貪婪的弊予,總是嘗試匹配盡可能多的字符,非貪婪則相反开财,總是嘗試匹配盡可能少的字符汉柒。
在“*”误褪、“?”、“+”、“{m,n}”后面加上预烙?,使貪婪變非貪婪嘀略。
import re
print(re.match('.*\d','a22222').group())
#a22222
print(re.match('.*?\d','a22222').group())
#a2
import re
content='aacbacbcwr'
pattern=re.compile('a.*b') #默認(rèn)的貪婪模式可以匹配到最后一個(gè)b
result=pattern.search(content)
print(result.group())
#aacbacb
pattern=re.compile('a.*?b') #非貪婪模式可以匹配到第一個(gè)b
result=pattern.search(content)
print(result.group())
#aacb
課后作業(yè)·問答題
- 匹配長(zhǎng)度8-10位的用戶密碼(以字母開頭,包含字母乓诽、數(shù)字和下劃線)
- 驗(yàn)證用戶名帜羊,長(zhǎng)度為6-18位的英文字母組成
- 郵箱驗(yàn)證123、163郵箱:16-18個(gè)字符鸠天,可以使用字母讼育、數(shù)字、下劃線粮宛,需要以字母開頭
- 匹配手機(jī)號(hào)碼(11位數(shù)字)
移動(dòng)號(hào)碼段:139窥淆、138、137巍杈、136忧饭、135、134筷畦、150词裤、151、152鳖宾、157吼砂、158、159鼎文、182渔肩、183、187拇惋、188周偎、147
聯(lián)通號(hào)碼段:130、131撑帖、132蓉坎、136、185胡嘿、186蛉艾、145
電信號(hào)碼段:133、153、180勿侯、189