47-re模塊

re模塊

在Python中遵馆,通過內(nèi)置的re模塊提供對(duì)正則表達(dá)式的支持。正則表達(dá)式會(huì)被編譯成一系列的字節(jié)碼,然后由通過C編寫的正則表達(dá)式引擎進(jìn)行執(zhí)行古今。該引擎自從Python1.6被內(nèi)置以來,近20年時(shí)間未有發(fā)生過變化

re模塊支持下面的正則語(yǔ)法:

"."      
"^"      
"$" 
"*"     
"+"      
"?"      
*?,+?,?? 
{m,n}    
{m,n}?   
"\\"     
[]      
"|"      
(...)    
(?aiLmsux)
(?:...)  
(?P<name>...) 
(?P=name)     
(?#...)  
(?=...) 
(?!...) 
(?<=...) 
(?<!...) 
(?(id/name)yes|no)

提供了下面的方法進(jìn)行字符串的查找滔以、替換和分割等各種處理操作

方法 描述 返回值
compile(pattern[, flags]) 根據(jù)包含正則表達(dá)式的字符串創(chuàng)建模式對(duì)象 re對(duì)象
search(pattern, string[, flags]) 在字符串中查找 第一個(gè)匹配到的對(duì)象或者None
match(pattern, string[, flags]) 在字符串的開始處匹配模式 在字符串開頭匹配到的對(duì)象或者None
split(pattern, string[, maxsplit=0,flags]) 根據(jù)模式的匹配項(xiàng)來分割字符串 分割后的字符串列表
findall(pattern, string,flags) 列出字符串中模式的所有匹配項(xiàng) 所有匹配到的字符串列表
sub(pat,repl, string[,count=0,flags]) 將字符串中所有的pat的匹配項(xiàng)用repl替換 完成替換后的新字符串
finditer(pattern, string,flags) 將所有匹配到的項(xiàng)生成一個(gè)迭代器 所有匹配到的字符串組合成的迭代器
subn(pat,repl, string[,count=0,flags]) 在替換字符串后捉腥,同時(shí)報(bào)告替換的次數(shù) 完成替換后的新字符串及替換次數(shù)
escape(string) 將字符串中所有特殊正則表達(dá)式字符串轉(zhuǎn)義 轉(zhuǎn)義后的字符串
purge(pattern) 清空正則表達(dá)式
template(pattern[,flags]) 編譯一個(gè)匹配模板 模式對(duì)象
fullmatch(pattern, string[, flags]) match方法的全字符串匹配版本 類似match的返回值

反斜杠的困擾:\

與大多數(shù)編程語(yǔ)言相同,正則表達(dá)式里使用\作為轉(zhuǎn)義字符你画,這可能造成反斜杠困擾抵碟。假如需要匹配文本中的字符\,那么使用編程語(yǔ)言表示的正則表達(dá)式里將需要4個(gè)反斜杠\\\\坏匪。前兩個(gè)和后兩個(gè)分別用于在編程語(yǔ)言里轉(zhuǎn)義成反斜杠拟逮,轉(zhuǎn)換成兩個(gè)反斜杠后再在正則表達(dá)式里轉(zhuǎn)義成一個(gè)反斜杠。為了方便我們使用個(gè)适滓,Python提供了原生字符串的功能敦迄,很好地解決了這個(gè)問題,這個(gè)例子中的正則表達(dá)式可以使用r"\\"表示凭迹。同樣罚屋,匹配一個(gè)數(shù)字的"\\d"可以直接寫成r"\d"。有了原生字符串嗅绸,你再也不用擔(dān)心是不是漏寫了反斜杠脾猛,寫出來的表達(dá)式也更直觀。

compile(pattern, flags=0)

這個(gè)方法是re模塊的工廠方法鱼鸠,用于將字符串形式的正則表達(dá)式編譯為Pattern模式對(duì)象猛拴,可以實(shí)現(xiàn)更高效率的匹配喉刘。第二個(gè)參數(shù)flag是匹配模式。

使用compile()完成一次轉(zhuǎn)換后漆弄,再次使用該匹配模式的時(shí)候就不用進(jìn)行轉(zhuǎn)換了睦裳。經(jīng)過compile()轉(zhuǎn)換的正則表達(dá)式對(duì)象也能使用普通的re方法。其用法如下:

import re
pat = re.compile(r"abc")
pat.match("abc123")
<_sre.SRE_Match object; span=(0, 3), match='abc'>

經(jīng)過compile()方法編譯過后的返回值是個(gè)re對(duì)象撼唾,它可以調(diào)用match()廉邑、search()、findall()等其他方法,但其他方法不能調(diào)用compile()方法倒谷。實(shí)際上蛛蒙,match()和search()等方法在使用前,Python內(nèi)部幫你進(jìn)行了compile的步驟渤愁。

re.match(r"abc","abc123").compile()
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    re.match(r"abc","abc123").compile()
AttributeError: '_sre.SRE_Match' object has no attribute 'compile'

match(pattern, string, flags=0)

match()方法會(huì)在給定字符串的開頭進(jìn)行匹配牵祟,如果匹配不成功則返回None,匹配成功返回一個(gè)匹配對(duì)象抖格,這個(gè)對(duì)象有個(gè)group()方法诺苹,可以將匹配到的字符串給出。

ret = re.match(r"abc","ab1c123")
print(ret)
None
re.match(r"abc","abc123")
<_sre.SRE_Match object; span=(0, 3), match='abc'>
obj = re.match(r"abc","abc123")
obj.group()
'abc'

search(pattern, string, flags=0)

在文本內(nèi)查找雹拄,返回第一個(gè)匹配到的字符串收奔。它的返回值類型和使用方法與match()是一樣的,唯一的區(qū)別就是查找的位置不用固定在文本的開頭滓玖。

obj = re.search(r"abc","123abc456abc789")
obj
<_sre.SRE_Match object; span=(3, 6), match='abc'>
obj.group()
'abc'
obj.start()
3
obj.end()
6
obj.span()
(3, 6)

findall(pattern, string, flags=0)

作為re模塊的三大搜索函數(shù)之一坪哄,findall()和match()、search()的不同之處在于势篡,前兩者都是單值匹配翩肌,找到一個(gè)就忽略后面,直接返回不再查找了禁悠。而findall是全文查找念祭,它的返回值是一個(gè)匹配到的字符串的列表。這個(gè)列表沒有g(shù)roup()方法绷蹲,沒有start棒卷、end、span祝钢,更不是一個(gè)匹配對(duì)象比规,僅僅是個(gè)列表!如果一項(xiàng)都沒有匹配到那么返回一個(gè)空列表拦英。

obj = re.findall(r"abc","123abc456abc789")
obj
['abc', 'abc']
obj.group()
Traceback (most recent call last):
  File "<pyshell#37>", line 1, in <module>
    obj.group()
AttributeError: 'list' object has no attribute 'group'
obj = re.findall(r"ABC","123abc456abc789")
print(obj)
[]

split(pattern, string, maxsplit=0, flags=0)

re模塊的split()方法和字符串的split()方法很相似蜒什,都是利用特定的字符去分割字符串。但是re模塊的split()可以使用正則表達(dá)式疤估,因此更靈活灾常,更強(qiáng)大霎冯,而且還有“殺手锏” 。

s = "8+7*5+6/3"
import re
a_list = re.split(r"[\+\-\*\/]",s)
a_list
['8', '7', '5', '6', '3']

split有個(gè)參數(shù)maxsplit钞瀑,用于指定分割的次數(shù):

a_list = re.split(r"[\+\-\*\/]",s,maxsplit= 2)
a_list
['8', '7', '5+6/3']

sub(pattern, repl, string, count=0, flags=0)

sub()方法類似字符串的replace()方法沈撞,用指定的內(nèi)容替換匹配到的字符,可以指定替換次數(shù)雕什。

s = "i am jack! i am nine years old ! i like swiming!"
import re
s = re.sub(r"i","I",s)
s
'I am jack! I am nIne years old ! I lIke swImIng!'

分組功能

Python的re模塊有一個(gè)分組功能缠俺。所謂的分組就是去已經(jīng)匹配到的內(nèi)容里面再篩選出需要的內(nèi)容,相當(dāng)于二次過濾贷岸。實(shí)現(xiàn)分組靠圓括號(hào)()壹士,而獲取分組的內(nèi)容靠的是group()、groups()和groupdict()方法偿警,其實(shí)前面我們已經(jīng)展示過躏救。re模塊里的幾個(gè)重要方法在分組上,有不同的表現(xiàn)形式螟蒸,需要區(qū)別對(duì)待盒使。

例一:match()方法,不分組時(shí)的情況:

import re
origin = "hasdfi123123safd"
# 不分組時(shí)的情況
r = re.match("h\w+", origin)
print(r.group())         # 獲取匹配到的整體結(jié)果
print(r.groups())        # 獲取模型中匹配到的分組結(jié)果元組
print(r.groupdict())     # 獲取模型中匹配到的分組中所有key的字典

結(jié)果:
hasdfi123123safd
()
{}

例二:match()方法尿庐,有分組的情況(注意圓括號(hào)V也馈)

import re
origin = "hasdfi123123safd123"
# 有分組
r = re.match("h(\w+).*(?P<name>\d)$", origin)
print(r.group())  # 獲取匹配到的整體結(jié)果
print(r.group(1))  # 獲取匹配到的分組1的結(jié)果
print(r.group(2))  # 獲取匹配到的分組2的結(jié)果
print(r.groups())  # 獲取模型中匹配到的分組結(jié)果元組
print(r.groupdict())  # 獲取模型中匹配到的分組中所有key的字典

執(zhí)行結(jié)果:
hasdfi123123safd123
asdfi123123safd12
3
('asdfi123123safd12', '3')
{'name': '3'}

例三呢堰,search()方法抄瑟,有分組的情況:

import re
origin = "sdfi1ha23123safd123"      # 注意這里對(duì)匹配對(duì)象做了下調(diào)整
# 有分組
r = re.search("h(\w+).*(?P<name>\d)$", origin)
print(r.group())  
print(r.group(0))  
print(r.group(1))  
print(r.group(2))
print(r.groups())  
print(r.groupdict()) 

執(zhí)行結(jié)果:
ha23123safd123
ha23123safd123
a23123safd12
3
('a23123safd12', '3')
{'name': '3'}

例四,findall()方法枉疼,沒有分組的情況:

import re
origin = "has something have do"
# 無(wú)分組
r = re.findall("h\w+", origin)
print(r)

執(zhí)行結(jié)果:
['has', 'hing', 'have']
# 一切看起來沒什么不一樣

例五皮假,findall()方法,有一個(gè)分組的情況:

import re
origin = "has something have do"
# 一個(gè)分組
r = re.findall("h(\w+)", origin)
print(r)

執(zhí)行結(jié)果:
['as', 'ing', 'ave']

例六骂维,findall()方法惹资,有兩個(gè)以上分組的情況:

import re
origin = "hasabcd something haveabcd do"    # 字符串調(diào)整了一下
# 兩個(gè)分組
r = re.findall("h(\w+)a(bc)d", origin)
print(r)

運(yùn)行結(jié)果:
[('as', 'bc'), ('ave', 'bc')]

如何拆分含有多種分隔符的字符串

我們要把某字符串依據(jù)分隔符號(hào)拆分不同的字段,該字符串包含多種不同的分隔符航闺,例如:
s = 'ab;cd|efg|hi|hi,jkl\topq;str,ubw\asyd'
其中<,>,<;>,<|>,<\t> 都是分隔符號(hào),如何處理褪测?

第一種方法,可以連續(xù)使用str.split()方法潦刃,每次處理一種分割符號(hào)

def mySplit(s,ds):
    res = [s]
    for d in ds:
        t = []
        list(map(lambda x:t.extend(x.split(d)),res))
        res = t
    return res
s = 'ab;cd|efg|hi|hi,jkl\topq;str,ubw\x07syd'
print(mySplit(s,',;|\t'))

如果出現(xiàn)連續(xù)的分割符號(hào)侮措,會(huì)出現(xiàn)空字符的情況,這時(shí)候如果我們想去掉空字符串乖杠。
return [x for x in res if x]
用列表推導(dǎo)式可以完成這個(gè)需求分扎。

第二種方法,使用正則表達(dá)式的re.split()方法胧洒,一次性拆分字符串

import re
re.split(r'[,;\t|]+',s)

某軟件要求畏吓,從網(wǎng)絡(luò)抓取各個(gè)城市氣溫信息墨状,并依次顯示
北京:15-17
天津:17-22
長(zhǎng)春:12-18
如果一次抓取所有城市天氣再顯示,顯示第一個(gè)城市氣溫時(shí)菲饼,有很高的延遲肾砂,并且浪費(fèi)存儲(chǔ)空間,我們期望以用時(shí)訪問的策略宏悦,并且能把所有城市氣溫封裝到一個(gè)對(duì)象里通今,可用for語(yǔ)句進(jìn)行迭代,如何解決肛根?

import requests

def getWeather(city):
    r = requests.get('http://wthrcdn.etouch.cn/weather_mini?city='+city)
    data = r.json()['data']['forecast'][0]
    return '%s:%s,%s'%(city,data['low'],data['high'])

print(getWeather('北京'))

如何調(diào)整字符串中文本的格式

日期格式為'yyyy-mm-dd':

image.png

我們想把其中日期改為美國(guó)日期的格式'mm/dd/yyyy'
'2016-05-23'=>'05/23/2016',應(yīng)該如何處理辫塌?

import re
re.sub('(\d{4})-(\d{2})-(\d{2})',r'\2/\3/\1',file)

re.sub('(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})',r'\g<month>/\g<day>/\g<year>',file)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市派哲,隨后出現(xiàn)的幾起案子臼氨,更是在濱河造成了極大的恐慌,老刑警劉巖芭届,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件储矩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡褂乍,警方通過查閱死者的電腦和手機(jī)持隧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逃片,“玉大人屡拨,你說我怎么就攤上這事∪焓担” “怎么了呀狼?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)损离。 經(jīng)常有香客問我哥艇,道長(zhǎng),這世上最難降的妖魔是什么僻澎? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任貌踏,我火速辦了婚禮,結(jié)果婚禮上窟勃,老公的妹妹穿的比我還像新娘祖乳。我一直安慰自己,他們只是感情好拳恋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布凡资。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪隙赁。 梳的紋絲不亂的頭發(fā)上垦藏,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音伞访,去河邊找鬼掂骏。 笑死,一個(gè)胖子當(dāng)著我的面吹牛厚掷,可吹牛的內(nèi)容都是我干的弟灼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼冒黑,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼田绑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起抡爹,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤掩驱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后冬竟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體欧穴,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年泵殴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涮帘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡笑诅,死狀恐怖调缨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情苟鸯,我是刑警寧澤同蜻,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站早处,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏瘫析。R本人自食惡果不足惜砌梆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望贬循。 院中可真熱鬧咸包,春花似錦、人聲如沸杖虾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至坟比,卻和暖如春芦鳍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背葛账。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工柠衅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人籍琳。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓菲宴,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親趋急。 傳聞我的和親對(duì)象是個(gè)殘疾皇子喝峦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Python中的正則表達(dá)式(re) import rere.match #從開始位置開始匹配,如果開頭沒有則無(wú)re...
    BigJeffWang閱讀 7,081評(píng)論 0 99
  • re模塊手冊(cè) 本模塊提供了和Perl里的正則表達(dá)式類似的功能呜达,不關(guān)是正則表達(dá)式本身還是被搜索的字符串愈犹,都可以...
    喜歡吃栗子閱讀 4,009評(píng)論 0 13
  • 搞懂Python 正則表達(dá)式用法 Python 正則表達(dá)式 正則表達(dá)式是一個(gè)特殊的字符序列,它能幫助你方便的檢查一...
    廈熱閱讀 1,582評(píng)論 0 2
  • 舍友1:昨晚你在看小說闻丑? 我:對(duì)啊漩怎,怎么了? 舍友1:沒有嗦嗡,昨晚熄燈之后看你手機(jī)還在亮勋锤,而且在我看完電視劇大結(jié)局后...
    會(huì)飛的船閱讀 269評(píng)論 4 0
  • 沒有冗長(zhǎng)的開場(chǎng),張?jiān)洪L(zhǎng)開門見山:“同事們不好意思緊急找你們開會(huì)侥祭!是有要緊的事情需要同事們共同商量叁执。沒錯(cuò),還是為了重...
    碼字致富的朱榮發(fā)閱讀 569評(píng)論 0 2