python re模块详解_python 详解re模块
本文介紹了Python對(duì)于正則表達(dá)式的支持,包括正則表達(dá)式基礎(chǔ)以及Python正則表達(dá)式標(biāo)準(zhǔn)庫(kù)的完整介紹及使用示例。本文的內(nèi)容不包括如何編寫高效的正則表達(dá)式、如何優(yōu)化正則表達(dá)式,這些主題請(qǐng)查看其他教程。
注意:本文基于Python2.4完成;如果看到不明白的詞匯請(qǐng)記得百度谷歌或維基,whatever。
尊重作者的勞動(dòng),轉(zhuǎn)載請(qǐng)注明作者及原文地址 >.
1. 正則表達(dá)式基礎(chǔ)
1.1. 簡(jiǎn)單介紹
正則表達(dá)式并不是Python的一部分。正則表達(dá)式是用于處理字符串的強(qiáng)大工具,擁有自己獨(dú)特的語(yǔ)法以及一個(gè)獨(dú)立的處理引擎,效率上可能不如str自帶的方法,但功能十分強(qiáng)大。得益于這一點(diǎn),在提供了正則表達(dá)式的語(yǔ)言里,正則表達(dá)式的語(yǔ)法都是一樣的,區(qū)別只在于不同的編程語(yǔ)言實(shí)現(xiàn)支持的語(yǔ)法數(shù)量不同;但不用擔(dān)心,不被支持的語(yǔ)法通常是不常用的部分。如果已經(jīng)在其他語(yǔ)言里使用過(guò)正則表達(dá)式,只需要簡(jiǎn)單看一看就可以上手了。
下圖展示了使用正則表達(dá)式進(jìn)行匹配的流程:
正則表達(dá)式的大致匹配過(guò)程是:依次拿出表達(dá)式和文本中的字符比較,如果每一個(gè)字符都能匹配,則匹配成功;一旦有匹配不成功的字符則匹配失敗。如果表達(dá)式中有量詞或邊界,這個(gè)過(guò)程會(huì)稍微有一些不同,但也是很好理解的,看下圖中的示例以及自己多使用幾次就能明白。
下圖列出了Python支持的正則表達(dá)式元字符和語(yǔ)法:
1.2. 數(shù)量詞的貪婪模式與非貪婪模式
正則表達(dá)式通常用于在文本中查找匹配的字符串。Python里數(shù)量詞默認(rèn)是貪婪的(在少數(shù)語(yǔ)言里也可能是默認(rèn)非貪婪),總是嘗試匹配盡可能多的字符;非貪婪的則相反,總是嘗試匹配盡可能少的字符。例如:正則表達(dá)式"ab*"如果用于查找"abbbc",將找到"abbb"。而如果使用非貪婪的數(shù)量詞"ab*?",將找到"a"。
1.3. 反斜杠的困擾
與大多數(shù)編程語(yǔ)言相同,正則表達(dá)式里使用"\"作為轉(zhuǎn)義字符,這就可能造成反斜杠困擾。假如你需要匹配文本中的字符"\",那么使用編程語(yǔ)言表示的正則表達(dá)式里將需要4個(gè)反斜杠"\\\\":前兩個(gè)和后兩個(gè)分別用于在編程語(yǔ)言里轉(zhuǎn)義成反斜杠,轉(zhuǎn)換成兩個(gè)反斜杠后再在正則表達(dá)式里轉(zhuǎn)義成一個(gè)反斜杠。Python里的原生字符串很好地解決了這個(gè)問(wèn)題,這個(gè)例子中的正則表達(dá)式可以使用r"\\"表示。同樣,匹配一個(gè)數(shù)字的"\\d"可以寫成r"\d"。有了原生字符串,你再也不用擔(dān)心是不是漏寫了反斜杠,寫出來(lái)的表達(dá)式也更直觀。
1.4. 匹配模式
正則表達(dá)式提供了一些可用的匹配模式,比如忽略大小寫、多行匹配等,這部分內(nèi)容將在Pattern類的工廠方法re.compile(pattern[, flags])中一起介紹。
2. re模塊
2.1. 開始使用re
Python通過(guò)re模塊提供對(duì)正則表達(dá)式的支持。使用re的一般步驟是先將正則表達(dá)式的字符串形式編譯為Pattern實(shí)例,然后使用Pattern實(shí)例處理文本并獲得匹配結(jié)果(一個(gè)Match實(shí)例),最后使用Match實(shí)例獲得信息,進(jìn)行其他的操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# encoding: UTF-8
import re
# 將正則表達(dá)式編譯成Pattern對(duì)象
pattern= re.compile(r'hello')
# 使用Pattern匹配文本,獲得匹配結(jié)果,無(wú)法匹配時(shí)將返回None
match= pattern.match('hello world!')
if match:
# 使用Match獲得分組信息
print match.group()
### 輸出 ###
# hello
re.compile(strPattern[, flag]):
這個(gè)方法是Pattern類的工廠方法,用于將字符串形式的正則表達(dá)式編譯為Pattern對(duì)象。 第二個(gè)參數(shù)flag是匹配模式,取值可以使用按位或運(yùn)算符'|'表示同時(shí)生效,比如re.I | re.M。另外,你也可以在regex字符串中指定模式,比如re.compile('pattern', re.I | re.M)與re.compile('(?im)pattern')是等價(jià)的。 可選值有:
re.I(re.IGNORECASE): 忽略大小寫(括號(hào)內(nèi)是完整寫法,下同)
M(MULTILINE): 多行模式,改變'^'和'$'的行為(參見上圖)
S(DOTALL): 點(diǎn)任意匹配模式,改變'.'的行為
L(LOCALE): 使預(yù)定字符類 \w \W \b \B \s \S 取決于當(dāng)前區(qū)域設(shè)定
U(UNICODE): 使預(yù)定字符類 \w \W \b \B \s \S \d \D 取決于unicode定義的字符屬性
X(VERBOSE): 詳細(xì)模式。這個(gè)模式下正則表達(dá)式可以是多行,忽略空白字符,并可以加入注釋。以下兩個(gè)正則表達(dá)式是等價(jià)的:
1
2
3
4
a= re.compile(r"""\d + # the integral part
\. # the decimal point
\d * # some fractional digits""", re.X)
b= re.compile(r"\d+\.\d*")
re提供了眾多模塊方法用于完成正則表達(dá)式的功能。這些方法可以使用Pattern實(shí)例的相應(yīng)方法替代,唯一的好處是少寫一行re.compile()代碼,但同時(shí)也無(wú)法復(fù)用編譯后的Pattern對(duì)象。這些方法將在Pattern類的實(shí)例方法部分一起介紹。如上面這個(gè)例子可以簡(jiǎn)寫為:
1
2
m= re.match(r'hello','hello world!')
print m.group()
re模塊還提供了一個(gè)方法escape(string),用于將string中的正則表達(dá)式元字符如*/+/?等之前加上轉(zhuǎn)義符再返回,在需要大量匹配元字符時(shí)有那么一點(diǎn)用。
2.2. Match
Match對(duì)象是一次匹配的結(jié)果,包含了很多關(guān)于此次匹配的信息,可以使用Match提供的可讀屬性或方法來(lái)獲取這些信息。
屬性:
string: 匹配時(shí)使用的文本。
re: 匹配時(shí)使用的Pattern對(duì)象。
pos: 文本中正則表達(dá)式開始搜索的索引。值與Pattern.match()和Pattern.seach()方法的同名參數(shù)相同。
endpos: 文本中正則表達(dá)式結(jié)束搜索的索引。值與Pattern.match()和Pattern.seach()方法的同名參數(shù)相同。
lastindex: 最后一個(gè)被捕獲的分組在文本中的索引。如果沒(méi)有被捕獲的分組,將為None。
lastgroup: 最后一個(gè)被捕獲的分組的別名。如果這個(gè)分組沒(méi)有別名或者沒(méi)有被捕獲的分組,將為None。
方法:
group([group1, …]): 獲得一個(gè)或多個(gè)分組截獲的字符串;指定多個(gè)參數(shù)時(shí)將以元組形式返回。group1可以使用編號(hào)也可以使用別名;編號(hào)0代表整個(gè)匹配的子串;不填寫參數(shù)時(shí),返回group(0);沒(méi)有截獲字符串的組返回None;截獲了多次的組返回最后一次截獲的子串。
groups([default]): 以元組形式返回全部分組截獲的字符串。相當(dāng)于調(diào)用group(1,2,…last)。default表示沒(méi)有截獲字符串的組以這個(gè)值替代,默認(rèn)為None。
groupdict([default]):返回以有別名的組的別名為鍵、以該組截獲的子串為值的字典,沒(méi)有別名的組不包含在內(nèi)。default含義同上。
start([group]): 返回指定的組截獲的子串在string中的起始索引(子串第一個(gè)字符的索引)。group默認(rèn)值為0。
end([group]):返回指定的組截獲的子串在string中的結(jié)束索引(子串最后一個(gè)字符的索引+1)。group默認(rèn)值為0。
span([group]):返回(start(group), end(group))。
expand(template): 將匹配到的分組代入template中然后返回。template中可以使用\id或\g、\g引用分組,但不能使用編號(hào)0。\id與\g是等價(jià)的;但\10將被認(rèn)為是第10個(gè)分組,如果你想表達(dá)\1之后是字符'0',只能使用\g<1>0。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import re
m= re.match(r'(\w+) (\w+)(?P.*)','hello world!')
print "m.string:", m.string
print "m.re:", m.re
print "m.pos:", m.pos
print "m.endpos:", m.endpos
print "m.lastindex:", m.lastindex
print "m.lastgroup:", m.lastgroup
print "m.group(1,2):", m.group(1,2)
print "m.groups():", m.groups()
print "m.groupdict():", m.groupdict()
print "m.start(2):", m.start(2)
print "m.end(2):", m.end(2)
print "m.span(2):", m.span(2)
print r"m.expand(r'\2 \1\3'):", m.expand(r'\2 \1\3')
### output ###
# m.string: hello world!
# m.re: <_sre.SRE_Pattern object at 0x016E1A38>
# m.pos: 0
# m.endpos: 12
# m.lastindex: 3
# m.lastgroup: sign
# m.group(1,2): ('hello', 'world')
# m.groups(): ('hello', 'world', '!')
# m.groupdict(): {'sign': '!'}
# m.start(2): 6
# m.end(2): 11
# m.span(2): (6, 11)
# m.expand(r'\2 \1\3'): world hello!
2.3. Pattern
Pattern對(duì)象是一個(gè)編譯好的正則表達(dá)式,通過(guò)Pattern提供的一系列方法可以對(duì)文本進(jìn)行匹配查找。
Pattern不能直接實(shí)例化,必須使用re.compile()進(jìn)行構(gòu)造。
Pattern提供了幾個(gè)可讀屬性用于獲取表達(dá)式的相關(guān)信息:
pattern: 編譯時(shí)用的表達(dá)式字符串。
flags: 編譯時(shí)用的匹配模式。數(shù)字形式。
groups: 表達(dá)式中分組的數(shù)量。
groupindex: 以表達(dá)式中有別名的組的別名為鍵、以該組對(duì)應(yīng)的編號(hào)為值的字典,沒(méi)有別名的組不包含在內(nèi)。
1
2
3
4
5
6
7
8
9
10
11
12
13
import re
p= re.compile(r'(\w+) (\w+)(?P.*)', re.DOTALL)
print "p.pattern:", p.pattern
print "p.flags:", p.flags
print "p.groups:", p.groups
print "p.groupindex:", p.groupindex
### output ###
# p.pattern: (\w+) (\w+)(?P.*)
# p.flags: 16
# p.groups: 3
# p.groupindex: {'sign': 3}
實(shí)例方法[ | re模塊方法]:
match(string[, pos[, endpos]]) | re.match(pattern, string[, flags]):這個(gè)方法將從string的pos下標(biāo)處起嘗試匹配pattern;如果pattern結(jié)束時(shí)仍可匹配,則返回一個(gè)Match對(duì)象;如果匹配過(guò)程中pattern無(wú)法匹配,或者匹配未結(jié)束就已到達(dá)endpos,則返回None。 pos和endpos的默認(rèn)值分別為0和len(string);re.match()無(wú)法指定這兩個(gè)參數(shù),參數(shù)flags用于編譯pattern時(shí)指定匹配模式。 注意:這個(gè)方法并不是完全匹配。當(dāng)pattern結(jié)束時(shí)若string還有剩余字符,仍然視為成功。想要完全匹配,可以在表達(dá)式末尾加上邊界匹配符'$'。 示例參見2.1小節(jié)。
search(string[, pos[, endpos]]) | re.search(pattern, string[, flags]):這個(gè)方法用于查找字符串中可以匹配成功的子串。從string的pos下標(biāo)處起嘗試匹配pattern,如果pattern結(jié)束時(shí)仍可匹配,則返回一個(gè)Match對(duì)象;若無(wú)法匹配,則將pos加1后重新嘗試匹配;直到pos=endpos時(shí)仍無(wú)法匹配則返回None。 pos和endpos的默認(rèn)值分別為0和len(string));re.search()無(wú)法指定這兩個(gè)參數(shù),參數(shù)flags用于編譯pattern時(shí)指定匹配模式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# encoding: UTF-8
import re
# 將正則表達(dá)式編譯成Pattern對(duì)象
pattern= re.compile(r'world')
# 使用search()查找匹配的子串,不存在能匹配的子串時(shí)將返回None
# 這個(gè)例子中使用match()無(wú)法成功匹配
match= pattern.search('hello world!')
if match:
# 使用Match獲得分組信息
print match.group()
### 輸出 ###
# world
split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]):按照能夠匹配的子串將string分割后返回列表。maxsplit用于指定最大分割次數(shù),不指定將全部分割。
1
2
3
4
5
6
7
import re
p= re.compile(r'\d+')
print p.split('one1two2three3four4')
### output ###
# ['one', 'two', 'three', 'four', '']
findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags]):搜索string,以列表形式返回全部能匹配的子串。
1
2
3
4
5
6
7
import re
p= re.compile(r'\d+')
print p.findall('one1two2three3four4')
### output ###
# ['1', '2', '3', '4']
finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags]):搜索string,返回一個(gè)順序訪問(wèn)每一個(gè)匹配結(jié)果(Match對(duì)象)的迭代器。
1
2
3
4
5
6
7
8
import re
p= re.compile(r'\d+')
for min p.finditer('one1two2three3four4'):
print m.group(),
### output ###
# 1 2 3 4
sub(repl, string[, count]) | re.sub(pattern, repl, string[, count]):使用repl替換string中每一個(gè)匹配的子串后返回替換后的字符串。 當(dāng)repl是一個(gè)字符串時(shí),可以使用\id或\g、\g引用分組,但不能使用編號(hào)0。 當(dāng)repl是一個(gè)方法時(shí),這個(gè)方法應(yīng)當(dāng)只接受一個(gè)參數(shù)(Match對(duì)象),并返回一個(gè)字符串用于替換(返回的字符串中不能再引用分組)。 count用于指定最多替換次數(shù),不指定時(shí)全部替換。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import re
p= re.compile(r'(\w+) (\w+)')
s= 'i say, hello world!'
print p.sub(r'\2 \1', s)
def func(m):
return m.group(1).title()+ ' ' + m.group(2).title()
print p.sub(func, s)
### output ###
# say i, world hello!
# I Say, Hello World!
subn(repl, string[, count]) |re.sub(pattern, repl, string[, count]):返回 (sub(repl, string[, count]), 替換次數(shù))。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import re
p= re.compile(r'(\w+) (\w+)')
s= 'i say, hello world!'
print p.subn(r'\2 \1', s)
def func(m):
return m.group(1).title()+ ' ' + m.group(2).title()
print p.subn(func, s)
### output ###
# ('say i, world hello!', 2)
# ('I Say, Hello World!', 2)
以上就是Python對(duì)于正則表達(dá)式的支持。熟練掌握正則表達(dá)式是每一個(gè)程序員必須具備的技能,這年頭沒(méi)有不與字符串打交道的程序了。筆者也處于初級(jí)階段,與君共勉,^_^
另外,圖中的特殊構(gòu)造部分沒(méi)有舉出例子,用到這些的正則表達(dá)式是具有一定難度的。有興趣可以思考一下,如何匹配不是以abc開頭的單詞,^_^
正則表達(dá)式 re模塊
hejiasheng 于 2014-02-10 07:00:17+00:00 更新訪問(wèn)次數(shù):1547
Regular Expression、regex或regexp,(縮寫為RE) 是指一個(gè)用來(lái)描述或者匹配一系列符合某個(gè)句法規(guī)則的字符串的單個(gè)字符串。
計(jì)算機(jī)里處理文本和數(shù)據(jù)是非常重要的事情。
一般匹配規(guī)則:?
1 字符串匹配
"abcd" 這種是沒(méi)有特殊規(guī)則,就是完全按照 字符去匹配。 例如:"hello,abcd" 可以匹配。 "hello,abc" 匹配不上。
>>>importre
>>>re.search("abcd","hello,abcd")
<_sre.SRE_Match objectat 0x994e2c0>
>>>re.search("abcd","hello,abdc")
2 選擇匹配 gray|grey ,“gray” 和"grey " 都能匹配上。 或者用 gr(a|e)y 規(guī)則來(lái)匹配后面2個(gè)單詞 "gray","grey"。
>>>printre.search("gray|grey","gray")
<_sre.SRE_Match objectat 0x994e2c0>
>>>printre.search("gray|grey","grey")
<_sre.SRE_Match objectat 0x994e2c0>
>>>printre.search("gray|grey","grcy")
None
>>>printre.search("gr(a|e)y","gray")
<_sre.SRE_Match objectat 0xb77268a0>
3 數(shù)量限定
‘+’加號(hào)代表前面的字符必須至少出現(xiàn)一次。(1次、或多次)。例如,“goo+gle”可以匹配google、gooogle、goooogle等;
?問(wèn)號(hào)代表前面的字符最多只可以出現(xiàn)一次。(0次、或1次)。例如,“colou?r”可以匹配color或者colour;
‘*’星號(hào)代表前面的字符可以不出現(xiàn),也可以出現(xiàn)一次或者多次。(0次、或1次、或多次)。例如,“0*42”可以匹配42、042、0042、00042等。>>>re.search("goo+gle","google")
<_sre.SRE_Match objectat 0xb7717e20>
>>>re.search("goo+gle","gogle")
>>>re.search("goo+gle","goooogle")
<_sre.SRE_Match objectat 0x994e2c0>
“?” 例子
>>>re.search("colou?r","color")
<_sre.SRE_Match objectat 0xb7717e20>
>>>re.search("colou?r","colour")
<_sre.SRE_Match objectat 0x994e2c0>
>>>re.search("colou?r","colouur")
>>>#對(duì)比 "+"
>>>re.search("colou+r","colouur")
<_sre.SRE_Match objectat 0xb7717e20>
>>>re.search("colou+r","color")
“*” 例子:
>>>re.search("goo*gle","google")
<_sre.SRE_Match objectat 0xb7717e20>
>>>re.search("goo*gle","gooogle")
<_sre.SRE_Match objectat 0x994e2c0>
4 [...] 括號(hào)里面包含的任意字符
b[aeou]d 匹配"bad","bed","bod","bud"
>>>re.search("b[aeoud]d","bad")
<_sre.SRE_Match objectat 0x994e2c0>
>>>re.search("b[aeoud]d","bed")
<_sre.SRE_Match objectat 0xb7717e20>
>>>re.search("b[aeoud]d","bud")
<_sre.SRE_Match objectat 0x994e2c0>
>>>re.search("b[aeoud]d","bcd")
>>>re.search("b[aeoud]d","baed")
匹配 [0-9],[0-9a-z]
>>>re.search('b[0-9a-z]d',"b12d")
>>>re.search('b[0-9a-z]d',"b1d")
<_sre.SRE_Match objectat 0xb7717e20>
>>>re.search('b[0-9a-z]d',"bad")
<_sre.SRE_Match objectat 0x994e2c0>
5 多字符匹配 {n}
[0-9]{3} : []以內(nèi)的字母、數(shù)字在后面字符串中出現(xiàn)的次數(shù)。 “hd543”,符合規(guī)則。 "hello32rew",不符合規(guī)則。
>>>re.search("[0-9]{3}","hd23")
>>>re.search("[0-9]{3}","hd232")
<_sre.SRE_Match objectat 0x92ec2c0>
>>>re.search("[0-9]{3}","hd234")
<_sre.SRE_Match objectat 0xb77bee20>
>>>
>>>re.search("[0-9]{4}","hd234")
>>>re.search("[0-9d]{4}","hd234")
<_sre.SRE_Match objectat 0x92ec2c0>
6. []{m,n}, 按照[]內(nèi)規(guī)則匹配 m---n之間個(gè)數(shù),m必須小于n。
7 "." 匹配任何1個(gè)字符。
>>>importre
>>>re.search('b.b',"beb")
<_sre.SRE_Match objectat 0xb7280170>
>>>re.search('b.b',"bab")
<_sre.SRE_Match objectat 0xb7280368>
>>>re.search('b.b',"badb")
>>>re.search('b..b',"badb")
<_sre.SRE_Match objectat 0xb7280170>
>>>
8 “^” 匹配字符串的開始
>>>re.search('^bad',"badb")
<_sre.SRE_Match objectat 0xb7280368>
>>>re.search('^ad',"badb")
>>>re.search('^.ad',"badb")
<_sre.SRE_Match objectat 0xb7280170>
>>>re.search('^..ad',"badb")
>>>
9
"$" 匹配字符串的結(jié)尾
>>>re.search('adb$',"badb")
<_sre.SRE_Match objectat 0xb7280170>
>>>re.search('.db$',"badb")
<_sre.SRE_Match objectat 0xb7280368>
10
'\d'匹配數(shù)字
‘\D' 匹配非數(shù)字>>>re.search('\d',"badec3b2v432")
<_sre.SRE_Match objectat 0xb7280368>
>>>re.search('\D',"badec3b2v432")
<_sre.SRE_Match objectat 0xb7280170>
>>>
11
'\w'匹配任意數(shù)字和字母
'\W'非數(shù)字和字母
12
'\s'匹配任意空白字符,相當(dāng)于[\t\n\r\f\v]
\S 匹配任意非空白字符,相當(dāng)于[^\t\n\r\f\v]
使用方法?
A)
compiled_pattern =re.compile(pattern)
result =compiled_pattern.match(string)
B)
result =re.match(pattern,string)
pattern,就是上面提到的規(guī)則。
除了match,以為還有幾個(gè)函數(shù),我們一起做說(shuō)明: match() 函數(shù)只在字符串的開始位置嘗試匹配正則表達(dá)式,也就是只報(bào)告從位置 0 開始的匹配情況。
search() 函數(shù)是掃描整個(gè)字符串來(lái)查找匹配。如果想要搜索整個(gè)字符串來(lái)尋找匹配,應(yīng)當(dāng)用 search()。 但search 返回第一個(gè)匹配的字符串。
split() 將字符串按照規(guī)則分成list。如果按照規(guī)則里面找不到,就不分割,返回原字符串。
>>>re.split(":","test:test1:test2")
['test','test1','test2']
findall() 函數(shù)搜索整個(gè)字符串,返回所有匹配項(xiàng)。返回一個(gè)list。
sub() 函數(shù) 查找并替換
>>>re.sub("one","num","one world, on dream",1)
'num world, on dream'
>>>re.sub("one","num","one world, one dream",1)
'num world, one dream'
>>>re.sub("one","num","one world, one dream",2)
'num world, num dream'
>>>
可以:
>>>p =re.compile('(one|two|three)')
>>>p.sub('num','one word two words three words')
'num word num words num words'
匹配網(wǎng)址的實(shí)例:
#coding=utf-8
importre
urls=r'fdsa... '
s =re.findall("",urls)
prints
非貪婪匹配 + 后結(jié)束標(biāo)記
all_buf =re.findall(r' ]',buf)
forn inall_buf:
printn
簡(jiǎn)單匹配 @ 后面的用戶正則
#s = "@fdsa;1232"
s ="fdsfds@fdsa你好.1, 232"
a =re.findall("""@(.*?)(?=[;,| '".?])""",s)
print a[0]
如果@后面沒(méi)有任何特殊符號(hào),就結(jié)束了匹配方法,加了$:
>>>a=re.compile("@(.*?)(?=[ ,'$]|$)")
>>>printa.findall("@sina @abd, @fds")
正則表達(dá)式的元字符有. ^ $ * ? { [ ] | ( ) .表示任意字符 []用來(lái)匹配一個(gè)指定的字符類別,所謂的字符類別就是你想匹配的一個(gè)字符集,對(duì)于字符集中的字符可以理解成或的關(guān)系。 ^ 如果放在字符串的開頭,則表示取非的意思。[^5]表示除了5之外的其他字符。而如果^不在字符串的開頭,則表示它本身。
具有重復(fù)功能的元字符: * 對(duì)于前一個(gè)字符重復(fù)0到無(wú)窮次 對(duì)于前一個(gè)字符重復(fù)1到無(wú)窮次 ?對(duì)于前一個(gè)字符重復(fù)0到1次 {m,n} 對(duì)于前一個(gè)字符重復(fù)次數(shù)在為m到n次,其中,{0,} = *,{1,} = , {0,1} = ? {m} 對(duì)于前一個(gè)字符重復(fù)m次
\d 匹配任何十進(jìn)制數(shù);它相當(dāng)于類 [0-9]。 \D 匹配任何非數(shù)字字符;它相當(dāng)于類 [^0-9]。 \s 匹配任何空白字符;它相當(dāng)于類 [ fv]。 \S 匹配任何非空白字符;它相當(dāng)于類 [^ fv]。 \w 匹配任何字母數(shù)字字符;它相當(dāng)于類 [a-zA-Z0-9_]。 \W 匹配任何非字母數(shù)字字符;它相當(dāng)于類 [^a-zA-Z0-9_]。
正則表達(dá)式(可以稱為REs,regex,regex pattens)是一個(gè)小巧的,高度專業(yè)化的編程語(yǔ)言,它內(nèi)嵌于python開發(fā)語(yǔ)言中,可通過(guò)re模塊使用。正則表達(dá)式的
pattern可以被編譯成一系列的字節(jié)碼,然后用C編寫的引擎執(zhí)行。下面簡(jiǎn)單介紹下正則表達(dá)式的語(yǔ)法
正則表達(dá)式包含一個(gè)元字符(metacharacter)的列表,列表值如下: . ^ $ * + ? { [ ] \ | ( )
1.元字符([ ]),它用來(lái)指定一個(gè)character class。所謂character classes就是你想要匹配的字符(character)的集合.字符(character)可以單個(gè)的列出,也可以通過(guò)"-"來(lái)分隔兩個(gè)字符來(lái)表示一 個(gè)范圍。例如,[abc]匹配a,b或者c當(dāng)中任意一個(gè)字符,[abc]也可以用字符區(qū)間來(lái)表示---[a-c].如果想要匹配單個(gè)大寫字母,你可以用 [A-Z]。
元字符(metacharacters)在character class里面不起作用,如[akm$]將匹配"a","k","m","$"中的任意一個(gè)字符。在這里元字符(metacharacter)"$"就是一個(gè)普通字符。
2.元字符[^]. 你可以用補(bǔ)集來(lái)匹配不在區(qū)間范圍內(nèi)的字符。其做法是把"^"作為類別的首個(gè)字符;其它地方的"^"只會(huì)簡(jiǎn)單匹配 "^"字符本身。例如,[^5] 將匹配除 "5" 之外的任意字符。同時(shí),在[ ]外,元字符^表示匹配字符串的開始,如"^ab+"表示以ab開頭的字符串。
舉例驗(yàn)證,
>>> m=re.search("^ab+","asdfabbbb")
>>> print m
None
>>> m=re.search("ab+","asdfabbbb")
>>> print m
<_sre.SRE_Match object at 0x011B1988>
>>> print m.group()
abbbb
上例不能用re.match,因?yàn)閙atch匹配字符串的開始,我們無(wú)法驗(yàn)證元字符"^"是否代表字符串的開始位置。
>>> m=re.match("^ab+","asdfabbbb")
>>> print m
None
>>> m=re.match("ab+","asdfabbbb")
>>> print m
None
#驗(yàn)證在元字符[]中,"^"在不同位置所代表的意義。
>>> re.search("[^abc]","abcd") #"^"在首字符表示取反,即abc之外的任意字符。
<_sre.SRE_Match object at 0x011B19F8>
>>> m=re.search("[^abc]","abcd")
>>> m.group()
'd'
>>> m=re.search("[abc^]","^") #如果"^"在[ ]中不是首字符,那么那就是一個(gè)普通字符
>>> m.group()
'^'
不過(guò)對(duì)于元字符”^”有這么一個(gè)疑問(wèn).官方文檔http://docs.python.org/library/re.html有關(guān)元字符”^”有這么一句話,Matches the start
of the string, and in MULTILINE mode also matches immediately after each newline.
我理解的是”^”匹配字符串的開始,在MULTILINE模式下,也匹配換行符之后。
>>> m=re.search("^a\w+","abcdfa\na1b2c3")
>>> m.group()
'abcdfa'
>>> m=re.search("^a\w+","abcdfa\na1b2c3",re.MULTILINE),
>>> m.group() #
'abcdfa'
我 認(rèn)為flag設(shè)定為re.MULTILINE,根據(jù)上面那段話,他也應(yīng)該匹配換行符之后,所以應(yīng)該有m.group應(yīng)該有"a1b2c3",但是結(jié)果沒(méi) 有,用findall來(lái)嘗試,可以找到結(jié)果。所以這里我理解之所以group里面沒(méi)有,是因?yàn)閟earch和match方法是匹配到就返回,而不是去匹配 所有。
>>> m=re.findall("^a\w+","abcdfa\na1b2c3",re.MULTILINE)
>>> m
['abcdfa', 'a1b2c3']
3. 元字符(\),元字符backslash。做為 Python 中的字符串字母,反斜杠后面可以加不同的字符以表示不同特殊意義。
它也可以用于取消所有的元字符,這樣你 就可以在模式中匹配它們了。例如,如果你需要匹配字符 "[" 或 "\",你可以在它們之前用反斜杠來(lái)取消它們的特殊意義: \[ 或 \\
4。元字符($)匹配字符串的結(jié)尾或者字符串結(jié)尾的換行之前。(在MULTILINE模式下,"$"也匹配換行之前)
正則表達(dá)式"foo"既匹配"foo"又匹配"foobar",而"foo$"僅僅匹配"foo".
>>> re.findall("foo.$","foo1\nfoo2\n")#匹配字符串的結(jié)尾的換行符之前。
['foo2']
>>> re.findall("foo.$","foo1\nfoo2\n",re.MULTILINE)
['foo1', 'foo2']
>>> m=re.search("foo.$","foo1\nfoo2\n")
>>> m
<_sre.SRE_Match object at 0x00A27170>
>>> m.group()
'foo2'
>>> m=re.search("foo.$","foo1\nfoo2\n",re.MULTILINE)
>>> m.group()
'foo1'
看來(lái)re.MULTILINE對(duì)$的影響還是蠻大的。
5.元字符(*),匹配0個(gè)或多個(gè)
6.元字符(?),匹配一個(gè)或者0個(gè)
7.元字符(+), 匹配一個(gè)或者多個(gè)
8,元字符(|), 表示"或",如A|B,其中A,B為正則表達(dá)式,表示匹配A或者B
9.元字符({})
{m},用來(lái)表示前面正則表達(dá)式的m次copy,如"a{5}",表示匹配5個(gè)”a”,即"aaaaa"
>>> re.findall("a{5}","aaaaaaaaaa")
['aaaaa', 'aaaaa']
>>> re.findall("a{5}","aaaaaaaaa")
['aaaaa']
{m.n}用來(lái)表示前面正則表達(dá)式的m到n次copy,嘗試匹配盡可能多的copy。
>>> re.findall("a{2,4}","aaaaaaaa")
['aaaa', 'aaaa']
通過(guò)上面的例子,可以看到{m,n},正則表達(dá)式優(yōu)先匹配n,而不是m,因?yàn)榻Y(jié)果不是["aa","aa","aa","aa"]
>>> re.findall("a{2}","aaaaaaaa")
['aa', 'aa', 'aa', 'aa']
{m,n}? 用來(lái)表示前面正則表達(dá)式的m到n次copy,嘗試匹配盡可能少的copy
>>> re.findall("a{2,4}?","aaaaaaaa")
['aa', 'aa', 'aa', 'aa']
10。元字符( "( )" ),用來(lái)表示一個(gè)group的開始和結(jié)束。
比較常用的有(REs),(?PREs),這是無(wú)名稱的組和有名稱的group,有名稱的group,可以通過(guò)matchObject.group(name)
獲取匹配的group,而無(wú)名稱的group可以通過(guò)從1開始的group序號(hào)來(lái)獲取匹配的組,如matchObject.group(1)。具體應(yīng)用將在下面的group()方法中舉例講解
11.元字符(.)
元字符“.”在默認(rèn)模式下,匹配除換行符外的所有字符。在DOTALL模式下,匹配所有字符,包括換行符。
>>> import re
>>> re.match(".","\n")
>>> m=re.match(".","\n")
>>> print m
None
>>> m=re.match(".","\n",re.DOTALL)
>>> print m
<_sre.SRE_Match object at 0x00C2CE20>
>>> m.group()
'\n'
下面我們首先來(lái)看一下Match Object對(duì)象擁有的方法,下面是常用的幾個(gè)方法的簡(jiǎn)單介紹
1.group([group1,…])
返回匹配到的一個(gè)或者多個(gè)子組。如果是一個(gè)參數(shù),那么結(jié)果就是一個(gè)字符串,如果是多個(gè)參數(shù),那么結(jié)果就是一個(gè)參數(shù)一個(gè)item的元組。group1的默 認(rèn)值為0(將返回所有的匹配值).如果groupN參數(shù)為0,相對(duì)應(yīng)的返回值就是全部匹配的字符串,如果group1的值是[1…99]范圍之內(nèi)的,那么 將匹配對(duì)應(yīng)括號(hào)組的字符串。如果組號(hào)是負(fù)的或者比pattern中定義的組號(hào)大,那么將拋出IndexError異常。如果pattern沒(méi)有匹配到,但 是group匹配到了,那么group的值也為None。如果一個(gè)pattern可以匹配多個(gè),那么組對(duì)應(yīng)的是樣式匹配的最后一個(gè)。另外,子組是根據(jù)括號(hào) 從左向右來(lái)進(jìn)行區(qū)分的。
>>> m=re.match("(\w+) (\w+)","abcd efgh, chaj")
>>> m.group() # 匹配全部
'abcd efgh'
>>> m.group(1) # 第一個(gè)括號(hào)的子組.
'abcd'
>>> m.group(2)
'efgh'
>>> m.group(1,2) # 多個(gè)參數(shù)返回一個(gè)元組
('abcd', 'efgh')
>>> m=re.match("(?P\w+) (?P\w+)","sam lee")
>>> m.group("first_name") #使用group獲取含有name的子組
'sam'
>>> m.group("last_name")
'lee'
下面把括號(hào)去掉
>>> m=re.match("\w+ \w+","abcd efgh, chaj")
>>> m.group()
'abcd efgh'
>>> m.group(1)
Traceback (most recent call last):
File "", line 1, in
m.group(1)
IndexError: no such group
If a group matches multiple times, only the last match is accessible:
如果一個(gè)組匹配多個(gè),那么僅僅返回匹配的最后一個(gè)的。
>>> m=re.match(r"(..)+","a1b2c3")
>>> m.group(1)
'c3'
>>> m.group()
'a1b2c3'
Group的默認(rèn)值為0,返回正則表達(dá)式pattern匹配到的字符串
>>> s="afkak1aafal12345adadsfa"
>>> pattern=r"(\d)\w+(\d{2})\w"
>>> m=re.match(pattern,s)
>>> print m
None
>>> m=re.search(pattern,s)
>>> m
<_sre.SRE_Match object at 0x00C2FDA0>
>>> m.group()
'1aafal12345a'
>>> m.group(1)
'1'
>>> m.group(2)
'45'
>>> m.group(1,2,0)
('1', '45', '1aafal12345a')
2。groups([default])
返回一個(gè)包含所有子組的元組。Default是用來(lái)設(shè)置沒(méi)有匹配到組的默認(rèn)值的。Default默認(rèn)是"None”,
>>> m=re.match("(\d+)\.(\d+)","23.123")
>>> m.groups()
('23', '123')
>>> m=re.match("(\d+)\.?(\d+)?","24") #這里的第二個(gè)\d沒(méi)有匹配到,使用默認(rèn)值"None"
>>> m.groups()
('24', None)
>>> m.groups("0")
('24', '0')
3.groupdict([default])
返回匹配到的所有命名子組的字典。Key是name值,value是匹配到的值。參數(shù)default是沒(méi)有匹配到的子組的默認(rèn)值。這里與groups()方法的參數(shù)是一樣的。默認(rèn)值為None
>>> m=re.match("(\w+) (\w+)","hello world")
>>> m.groupdict()
{}
>>> m=re.match("(?P\w+) (?P\w+)","hello world")
>>> m.groupdict()
{'secode': 'world', 'first': 'hello'}
通過(guò)上例可以看出,groupdict()對(duì)沒(méi)有name的子組不起作用
正則表達(dá)式對(duì)象
re.search(string[, pos[, endpos]])
掃描字符串string,查找與正則表達(dá)式匹配的位置。如果找到一個(gè)匹配就返回一個(gè)MatchObject對(duì)象(并不會(huì)匹配所有的)。如果沒(méi)有找到那么返回None。
第二個(gè)參數(shù)表示從字符串的那個(gè)位置開始,默認(rèn)是0
第三個(gè)參數(shù)endpos限定字符串最遠(yuǎn)被查找到哪里。默認(rèn)值就是字符串的長(zhǎng)度。.
>>> m=re.search("abcd", '1abcd2abcd')
>>> m.group() #找到即返回一個(gè)match object,然后根據(jù)該對(duì)象的方法,查找匹配到的結(jié)果。
'abcd'
>>> m.start()
1
>>> m.end()
5
>>> re.findall("abcd","1abcd2abcd")
['abcd', 'abcd']
re.split(pattern, string[, maxsplit=0, flags=0])
用pattern來(lái)拆分string。如果pattern有含有括號(hào),那么在pattern中所有的組也會(huì)返回。
>>> re.split("\W+","words,words,works",1)
['words', 'words,works']
>>> re.split("[a-z]","0A3b9z",re.IGNORECASE)
['0A3', '9', '']
>>> re.split("[a-z]+","0A3b9z",re.IGNORECASE)
['0A3', '9', '']
>>> re.split("[a-zA-Z]+","0A3b9z")
['0', '3', '9', '']
>>> re.split('[a-f]+', '0a3B9', re.IGNORECASE)#re.IGNORECASE用來(lái)忽略pattern中的大小寫。
['0', '3B9']
如果在split的時(shí)候捕獲了組,并且匹配字符串的開始,那么返回的結(jié)果將會(huì)以一個(gè)空串開始。
>>> re.split('(\W+)', '...words, words...')
['', '...', 'words', ', ', 'words', '...', '']
>>> re.split('(\W+)', 'words, words...')
['words', ', ', 'words', '...', '']
re.findall(pattern, string[, flags])
以list的形式返回string中所有與pattern匹配的不重疊的字符串。String從左向右掃描,匹配的返回結(jié)果也是以這個(gè)順序。
Return all non-overlapping matches of pattern in string, as a list of strings. The string is scanned left-to-right, and matches are returned in the order found. If one or more groups are present in the pattern, return a list of groups; this will be a list of tuples if the pattern has more than one group. Empty matches are included in the result unless they touch the beginning of another match.
>>> re.findall('(\W+)', 'words, words...')
[', ', '...']
>>> re.findall('(\W+)d', 'words, words...d')
['...']
>>> re.findall('(\W+)d', '...dwords, words...d')
['...', '...']
re.finditer(pattern, string[, flags])
與findall類似,只不過(guò)是返回list,而是返回了一個(gè)疊代器
我們來(lái)看一個(gè)sub和subn的例子
>>> re.sub("\d","abc1def2hijk","RE")
'RE'
>>> x=re.sub("\d","abc1def2hijk","RE")
>>> x
'RE'
>>> re.sub("\d","RE","abc1def2hijk",)
'abcREdefREhijk'
>>> re.subn("\d","RE","abc1def2hijk",)
('abcREdefREhijk', 2)
通過(guò)例子我們可以看出sub和subn的差別:sub返回替換后的字符串,而subn返回由替換后的字符串以及替換的個(gè)數(shù)組成的元組。
re.sub(pattern, repl, string[, count, flags])
用repl替換字符串string中的pattern。如果pattern沒(méi)有匹配到,那么返回的字符串沒(méi)有變化]。Repl可以是一個(gè)字符串,也可以是 一個(gè)function。如果是字符串,如果repl是個(gè)方法/函數(shù)。對(duì)于所有的pattern匹配到。他都回調(diào)用這個(gè)方法/函數(shù)。這個(gè)函數(shù)和方法使用單個(gè) match object作為參數(shù),然后返回替換后的字符串。下面是官網(wǎng)提供的例子:
>>> def dashrepl(matchobj):
... if matchobj.group(0) == '-': return ' '
... else: retu
總結(jié)
以上是生活随笔為你收集整理的python re模块详解_python 详解re模块的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: mysql 1066解决方法_MySQL
- 下一篇: python树莓派编程_python树莓