Python正則表達(dá)式re模塊手冊(cè)



re模塊手冊(cè)

? ? ? ?本模塊提供了和Perl里的正則表達(dá)式類似的功能,不關(guān)是正則表達(dá)式本身還是被搜索的字符串,都可以是Unicode字符,這點(diǎn)不用擔(dān)心,python會(huì)處理地和Ascii字符一樣漂亮。

正則表達(dá)式使用反斜桿(\)來(lái)轉(zhuǎn)義特殊字符,使其可以匹配字符本身,而不是指定其他特殊的含義。這可能會(huì)和python字面意義上的字符串轉(zhuǎn)義相沖突,這也許有些令人費(fèi)解。比如,要匹配一個(gè)反斜桿本身,你也許要用'\\\\'來(lái)做為正則表達(dá)式的字符串,因?yàn)檎齽t表達(dá)式要是\\,而字符串里,每個(gè)反斜桿都要寫成\\。

你也可以在字符串前加上 r 這個(gè)前綴來(lái)避免部分疑惑,因?yàn)?r 開頭的python字符串是 raw 字符串,所以里面的所有字符都不會(huì)被轉(zhuǎn)義,比如r'\n'這個(gè)字符串就是一個(gè)反斜桿加上一字母n,而'\n'我們知道這是個(gè)換行符。因此,上面的'\\\\'你也可以寫成r'\\',這樣,應(yīng)該就好理解很多了。可以看下面這段:

復(fù)制代碼代碼如下:

>>> import re

>>> s = '\x5c'? #0x5c就是反斜桿

>>> print s

\

>>> re.match('\\\\', s)? #這樣可以匹配

<_sre.SRE_Match object at 0xb6949e20>

>>> re.match(r'\\', s)? #這樣也可以

<_sre.SRE_Match object at 0x80ce2c0>

>>> re.match('\\', s)? #但是這樣不行

Traceback (most recent call last):

File "", line 1, in

File "/usr/lib/python2.6/re.py", line 137, in match

return _compile(pattern, flags).match(string)

File "/usr/lib/python2.6/re.py", line 245, in _compile

raise error, v # invalid expression

sre_constants.error: bogus escape (end of line)

>>>

另外值得一提的是,re模塊的方法,大多也就是RegexObject對(duì)象的方法,兩者的區(qū)別在于執(zhí)行效率。這個(gè)在最后再展開吧。

正則表達(dá)式語(yǔ)法

正則表達(dá)式(RE)指定一個(gè)與之匹配的字符集合;本模塊所提供的函數(shù),將可以用來(lái)檢查所給的字符串是否與指定的正則表達(dá)式匹配。

正則表達(dá)式可以被連接,從而形成新的正則表達(dá)式;例如A和B都是正則表達(dá)式,那么AB也是正則表達(dá)式。一般地,如果字符串p與A匹配,q與B匹配的話,那么字符串pq也會(huì)與AB匹配,但A或者B里含有邊界限定條件或者命名組操作的情況除外。也就是說(shuō),復(fù)雜的正則表達(dá)式可以用簡(jiǎn)單的連接而成。

正則表達(dá)式可以包含特殊字符和普通字符,大部分字符比如'A','a'和'0'都是普通字符,如果做為正則表達(dá)式,它們將匹配它們本身。由于正則表達(dá)式可以連接,所以連接多個(gè)普通字符而成的正則表達(dá)式last也將匹配'last'。(后面將用不帶引號(hào)的表示正則表達(dá)式,帶引號(hào)的表示字符串)

下面就來(lái)介紹正則表達(dá)式的特殊字符:

'.'

點(diǎn)號(hào),在普通模式,它匹配除換行符外的任意一個(gè)字符;如果指定了 DOTALL 標(biāo)記,匹配包括換行符以內(nèi)的任意一個(gè)字符。

'^'

尖尖號(hào),匹配一個(gè)字符串的開始,在 MULTILINE 模式下,也將匹配任意一個(gè)新行的開始。

'$'

美元符號(hào),匹配一個(gè)字符串的結(jié)尾或者字符串最后面的換行符,在 MULTILINE 模式下,也匹配任意一行的行尾。也就是說(shuō),普通模式下,foo.$去搜索'foo1\nfoo2\n'只會(huì)找到'foo2′,但是在 MULTILINE 模式,還能找到 ‘foo1′,而且就用一個(gè) $ 去搜索'foo\n'的話,會(huì)找到兩個(gè)空的匹配:一個(gè)是最后的換行符,一個(gè)是字符串的結(jié)尾,演示:

復(fù)制代碼代碼如下:

>>> re.findall('(foo.$)', 'foo1\nfoo2\n')

['foo2']

>>> re.findall('(foo.$)', 'foo1\nfoo2\n', re.MULTILINE)

['foo1', 'foo2']

>>> re.findall('($)', 'foo\n')

['', '']

'*'

星號(hào),指定將前面的RE重復(fù)0次或者任意多次,而且總是試圖盡量多次地匹配。

'+'

加號(hào),指定將前面的RE重復(fù)1次或者任意多次,而且總是試圖盡量多次地匹配。

'?'

問(wèn)號(hào),指定將前面的RE重復(fù)0次或者1次,如果有的話,也盡量匹配1次。

*?, +?, ??

從前面的描述可以看到'*','+'和'?'都是貪婪的,但這也許并不是我們說(shuō)要的,所以,可以在后面加個(gè)問(wèn)號(hào),將策略改為非貪婪,只匹配盡量少的RE。示例,體會(huì)兩者的區(qū)別:

復(fù)制代碼代碼如下:

>>> re.findall('<(.*)>', '

title

')

['H1>title

>>> re.findall('<(.*?)>', '

title

')

['H1', '/H1']

{m}

m是一個(gè)數(shù)字,指定將前面的RE重復(fù)m次。

{m,n}

m和n都是數(shù)字,指定將前面的RE重復(fù)m到n次,例如a{3,5}匹配3到5個(gè)連續(xù)的a。注意,如果省略m,將匹配0到n個(gè)前面的RE;如果省略n,將匹配n到無(wú)窮多個(gè)前面的RE;當(dāng)然中間的逗號(hào)是不能省略的,不然就變成前面那種形式了。

{m,n}?

前面說(shuō)的{m,n},也是貪婪的,a{3,5}如果有5個(gè)以上連續(xù)a的話,會(huì)匹配5個(gè),這個(gè)也可以通過(guò)加問(wèn)號(hào)改變。a{3,5}?如果可能的話,將只匹配3個(gè)a。

'\'

反斜桿,轉(zhuǎn)義'*','?'等特殊字符,或者指定一個(gè)特殊序列(下面會(huì)詳述)

由于之前所述的原因,強(qiáng)烈建議用raw字符串來(lái)表述正則。

[]

方括號(hào),用于指定一個(gè)字符的集合。可以單獨(dú)列出字符,也可以用'-'連接起止字符以表示一個(gè)范圍。特殊字符在中括號(hào)里將失效,比如[akm$]就表示字符'a','k','m',或'$',在這里$也變身為普通字符了。[a-z]匹配任意一個(gè)小寫字母,[a-zA-Z0-9]匹配任意一個(gè)字母或數(shù)字。如果你要匹配']'或'-'本身,你需要加反斜桿轉(zhuǎn)義,或者是將其置于中括號(hào)的最前面,比如[]]可以匹配']'

你還可以對(duì)一個(gè)字符集合取反,以匹配任意不在這個(gè)字符集合里的字符,取反操作用一個(gè)'^'放在集合的最前面表示,放在其他地方的'^'將不會(huì)起特殊作用。例如[^5]將匹配任意不是'5'的字符;[^^]將匹配任意不是'^'的字符。

注意:在中括號(hào)里,+、*、(、)這類字符將會(huì)失去特殊含義,僅作為普通字符。反向引用也不能在中括號(hào)內(nèi)使用。

'|'

管道符號(hào),A和B是任意的RE,那么A|B就是匹配A或者B的一個(gè)新的RE。任意個(gè)數(shù)的RE都可以像這樣用管道符號(hào)間隔連接起來(lái)。這種形式可以被用于組中(后面將詳述)。對(duì)于目標(biāo)字符串,被'|'分割的RE將自左至右一一被測(cè)試,一旦有一個(gè)測(cè)試成功,后面的將不再被測(cè)試,即使后面的RE可能可以匹配更長(zhǎng)的串,換句話說(shuō),'|'操作符是非貪婪的。要匹配字面意義上的'|',可以用反斜桿轉(zhuǎn)義:\|,或是包含在反括號(hào)內(nèi):[|]。

(...)

匹配圓括號(hào)里的RE匹配的內(nèi)容,并指定組的開始和結(jié)束位置。組里面的內(nèi)容可以被提取,也可以采用\number這樣的特殊序列,被用于后續(xù)的匹配。要匹配字面意義上的'('和')',可以用反斜桿轉(zhuǎn)義:\(、\),或是包含在反括號(hào)內(nèi):[(]、[)]。

(?...)

這是一個(gè)表達(dá)式的擴(kuò)展符號(hào)。'?'后的第一個(gè)字母決定了整個(gè)表達(dá)式的語(yǔ)法和含義,除了(?P...)以外,表達(dá)式不會(huì)產(chǎn)生一個(gè)新的組。下面介紹幾個(gè)目前已被支持的擴(kuò)展:

(?iLmsux)

'i'、'L'、'm'、's'、'u'、'x'里的一個(gè)或多個(gè)字母。表達(dá)式不匹配任何字符,但是指定相應(yīng)的標(biāo)志:re.I(忽略大小寫)、re.L(依賴locale)、re.M(多行模式)、re.S(.匹配所有字符)、re.U(依賴Unicode)、re.X(詳細(xì)模式)。關(guān)于各個(gè)模式的區(qū)別,下面會(huì)有專門的一節(jié)來(lái)介紹的。使用這個(gè)語(yǔ)法可以代替在re.compile()的時(shí)候或者調(diào)用的時(shí)候指定flag參數(shù)。

例如,上面舉過(guò)的例子,可以改寫成這樣(和指定了re.MULTILINE是一樣的效果):

復(fù)制代碼代碼如下:

>>> re.findall('(?m)(foo.$)', 'foo1\nfoo2\n')

['foo1', 'foo2']

另外,還要注意(?x)標(biāo)志如果有的話,要放在最前面。

(?:...)

匹配內(nèi)部的RE所匹配的內(nèi)容,但是不建立組。

(?P...)

和普通的圓括號(hào)類似,但是子串匹配到的內(nèi)容將可以用命名的name參數(shù)來(lái)提取。組的name必須是有效的python標(biāo)識(shí)符,而且在本表達(dá)式內(nèi)不重名。命名了的組和普通組一樣,也用數(shù)字來(lái)提取,也就是說(shuō)名字只是個(gè)額外的屬性。

演示一下:

復(fù)制代碼代碼如下:

>>> m=re.match('(?P[a-zA-Z_]\w*)', 'abc=123')

>>> m.group('var')

'abc'

>>> m.group(1)

'abc'

(?P=name)

匹配之前以name命名的組里的內(nèi)容。

演示一下:

復(fù)制代碼代碼如下:

>>> re.match('<(?P\w*)>.*', '

xxx

')? #這個(gè)不匹配

>>> re.match('<(?P\w*)>.*', '

xxx

')? #這個(gè)匹配

<_sre.SRE_Match object at 0xb69588e0>

(?#...)

注釋,圓括號(hào)里的內(nèi)容會(huì)被忽略。

(?=...)

如果 ... 匹配接下來(lái)的字符,才算匹配,但是并不會(huì)消耗任何被匹配的字符。例如 Isaac (?=Asimov) 只會(huì)匹配后面跟著 'Asimov' 的 'Isaac ',這個(gè)叫做“前瞻斷言”。

(?!...)

和上面的相反,只匹配接下來(lái)的字符串不匹配 ... 的串,這叫做“反前瞻斷言”。

(?<=...)

只有當(dāng)當(dāng)前位置之前的字符串匹配 ... ,整個(gè)匹配才有效,這叫“后顧斷言”。字符串'abcdef'可以匹配正則(?<=abc)def,因?yàn)闀?huì)后向查找3個(gè)字符,看是否為abc。所以內(nèi)置的子RE,需要是固定長(zhǎng)度的,比如可以是abc、a|b,但不能是a*、a{3,4}。注意這種RE永遠(yuǎn)不會(huì)匹配到字符串的開頭。舉個(gè)例子,找到連字符('-')后的單詞:

復(fù)制代碼代碼如下:

>>> m = re.search('(?<=-)\w+', 'spam-egg')

>>> m.group(0)

'egg'

(?

同理,這個(gè)叫做“反后顧斷言”,子RE需要固定長(zhǎng)度的,含義是前面的字符串不匹配 ... 整個(gè)才算匹配。

(?(id/name)yes-pattern|no-pattern)

如有由id或者name指定的組存在的話,將會(huì)匹配yes-pattern,否則將會(huì)匹配no-pattern,通常情況下no-pattern也可以省略。例如:(<)?(\w+@\w+(?:\.\w+)+)(?(1)>)可以匹配 '' 和 'user@host.com',但是不會(huì)匹配 '

下面列出以'\'開頭的特殊序列。如果某個(gè)字符沒有在下面列出,那么RE的結(jié)果會(huì)只匹配那個(gè)字母本身,比如,\$只匹配字面意義上的'$'。

\number

匹配number所指的組相同的字符串。組的序號(hào)從1開始。例如:(.+) \1可以匹配'the the'和'55 55',但不匹配'the end'。這種序列在一個(gè)正則表達(dá)式里最多可以有99個(gè),如果number以0開頭,或是有3位以上的數(shù)字,就會(huì)被當(dāng)做八進(jìn)制表示的字符了。同時(shí),這個(gè)也不能用于方括號(hào)內(nèi)。

\A

只匹配字符串的開始。

\b

匹配單詞邊界(包括開始和結(jié)束),這里的“單詞”,是指連續(xù)的字母、數(shù)字和下劃線組成的字符串。注意,\b的定義是\w和\W的交界,所以精確的定義有賴于UNICODE和LOCALE這兩個(gè)標(biāo)志位。

\B

和\b相反,\B匹配非單詞邊界。也依賴于UNICODE和LOCALE這兩個(gè)標(biāo)志位。

\d

未指定UNICODE標(biāo)志時(shí),匹配數(shù)字,等效于:[0-9]。指定了UNICODE標(biāo)志時(shí),還會(huì)匹配其他Unicode庫(kù)里描述為字符串的符號(hào)。便于理解,舉個(gè)例子(好不容易找的例子啊,呵呵):

復(fù)制代碼代碼如下:

#\u2076\和u2084分別是上標(biāo)的6和下標(biāo)的4,屬于unicode的DIGIT

>>> unistr = u'\u2076\u2084abc'

>>> print unistr

??abc

>>> print re.findall('\d+', unistr, re.U)[0]

??

\D

和\d相反,不多說(shuō)了。

\s

當(dāng)未指定UNICODE和LOCALE這兩個(gè)標(biāo)志位時(shí),匹配任何空白字符,等效于[ \t\n\r\f\v]。如果指定了LOCALE,則還要加LOCALE相關(guān)的空白字符;如果指定了UNICODE,還要加上UNICODE空白字符,如較常見的空寬度連接空格(\uFEFF)、零寬度非連接空格(\u200B)等。

\S

和\s相反,也不多說(shuō)。

\w

當(dāng)未指定UNICODE和LOCALE這兩個(gè)標(biāo)志位時(shí),等效于[a-zA-Z0-9_]。當(dāng)指定了LOCALE時(shí),為[0-9_]加上當(dāng)前LOCAL指定的字母。當(dāng)指定了UNICODE時(shí),為[0-9_]加上UNICODE庫(kù)里的所有字母。

\W

和\w相反,不多說(shuō)。

\Z

只匹配字符串的結(jié)尾。

匹配之搜索

python提供了兩種基于正則表達(dá)式的操作:匹配(match)從字符串的開始檢查字符串是否個(gè)正則匹配。而搜索(search)檢查字符串任意位置是否有匹配的子串(perl默認(rèn)就是如此)。

注意,即使search的正則以'^'開頭,match和search也還是有許多不同的。

復(fù)制代碼代碼如下:

>>> re.match("c", "abcdef")? # 不匹配

>>> re.search("c", "abcdef") # 匹配

<_sre.SRE_Match object at ...>

模塊的屬性和方法

re.compile(pattern[, flags])

把一個(gè)正則表達(dá)式pattern編譯成正則對(duì)象,以便可以用正則對(duì)象的match和search方法。

得到的正則對(duì)象的行為(也就是模式)可以用flags來(lái)指定,值可以由幾個(gè)下面的值OR得到。

以下兩段內(nèi)容在語(yǔ)法上是等效的:

復(fù)制代碼代碼如下:

prog = re.compile(pattern)

result = prog.match(string)

result = re.match(pattern, string)

區(qū)別是,用了re.compile以后,正則對(duì)象會(huì)得到保留,這樣在需要多次運(yùn)用這個(gè)正則對(duì)象的時(shí)候,效率會(huì)有較大的提升。再用上面用過(guò)的例子來(lái)演示一下,用相同的正則匹配相同的字符串,執(zhí)行100萬(wàn)次,就體現(xiàn)出compile的效率了(數(shù)據(jù)來(lái)自我那1.86G CPU的神舟本本):

復(fù)制代碼代碼如下:

>>> timeit.timeit(

...???? setup='''import re; reg = re.compile('<(?P\w*)>.*')''',

...???? stmt='''reg.match('

xxx

')''',

...???? number=1000000)

1.2062149047851562

>>> timeit.timeit(

...???? setup='''import re''',

...???? stmt='''re.match('<(?P\w*)>.*', '

xxx

')''',

...???? number=1000000)

4.4380838871002197

re.I

re.IGNORECASE

讓正則表達(dá)式忽略大小寫,這樣一來(lái),[A-Z]也可以匹配小寫字母了。此特性和locale無(wú)關(guān)。

re.L

re.LOCALE

讓\w、\W、\b、\B、\s和\S依賴當(dāng)前的locale。

re.M

re.MULTILINE

影響'^'和'$'的行為,指定了以后,'^'會(huì)增加匹配每行的開始(也就是換行符后的位置);'$'會(huì)增加匹配每行的結(jié)束(也就是換行符前的位置)。

re.S

re.DOTALL

影響'.'的行為,平時(shí)'.'匹配除換行符以外的所有字符,指定了本標(biāo)志以后,也可以匹配換行符。

re.U

re.UNICODE

讓\w、\W、\b、\B、\d、\D、\s和\S依賴Unicode庫(kù)。

re.X

re.VERBOSE

運(yùn)用這個(gè)標(biāo)志,你可以寫出可讀性更好的正則表達(dá)式:除了在方括號(hào)內(nèi)的和被反斜杠轉(zhuǎn)義的以外的所有空白字符,都將被忽略,而且每行中,一個(gè)正常的井號(hào)后的所有字符也被忽略,這樣就可以方便地在正則表達(dá)式內(nèi)部寫注釋了。也就是說(shuō),下面兩個(gè)正則表達(dá)式是等效的:

復(fù)制代碼代碼如下:

a = re.compile(r"""\d +? # the integral part

\.??? # the decimal point

\d *? # some fractional digits""", re.X)

b = re.compile(r"\d+\.\d*")

re.search(pattern, string[, flags])

掃描string,看是否有個(gè)位置可以匹配正則表達(dá)式pattern。如果找到了,就返回一個(gè)MatchObject的實(shí)例,否則返回None,注意這和找到長(zhǎng)度為0的子串含義是不一樣的。搜索過(guò)程受flags的影響。

re.match(pattern, string[, flags])

如果字符串string的開頭和正則表達(dá)式pattern匹配的話,返回一個(gè)相應(yīng)的MatchObject的實(shí)例,否則返回None

注意:要在字符串的任意位置搜索的話,需要使用上面的search()。

re.split(pattern, string[, maxsplit=0])

用匹配pattern的子串來(lái)分割string,如果pattern里使用了圓括號(hào),那么被pattern匹配到的串也將作為返回值列表的一部分。如果maxsplit不為0,則最多被分割為maxsplit個(gè)子串,剩余部分將整個(gè)地被返回。

復(fù)制代碼代碼如下:

>>> re.split('\W+', 'Words, words, words.')

['Words', 'words', 'words', '']

>>> re.split('(\W+)', 'Words, words, words.')

['Words', ', ', 'words', ', ', 'words', '.', '']

>>> re.split('\W+', 'Words, words, words.', 1)

['Words', 'words, words.']

如果正則有圓括號(hào),并且可以匹配到字符串的開始位置的時(shí)候,返回值的第一項(xiàng),會(huì)多出一個(gè)空字符串。匹配到字符結(jié)尾也是同樣的道理:

復(fù)制代碼代碼如下:

>>> re.split('(\W+)', '...words, words...')

['', '...', 'words', ', ', 'words', '...', '']

注意,split不會(huì)被零長(zhǎng)度的正則所分割,例如:

復(fù)制代碼代碼如下:

>>> re.split('x*', 'foo')

['foo']

>>> re.split("(?m)^$", "foo\n\nbar\n")

['foo\n\nbar\n']

re.findall(pattern, string[, flags])

以列表的形式返回string里匹配pattern的不重疊的子串。string會(huì)被從左到右依次掃描,返回的列表也是從左到右一次匹配到的。如果pattern里含有組的話,那么會(huì)返回匹配到的組的列表;如果pattern里有多個(gè)組,那么各組會(huì)先組成一個(gè)元組,然后返回值將是一個(gè)元組的列表。

由于這個(gè)函數(shù)不會(huì)涉及到MatchObject之類的概念,所以,對(duì)新手來(lái)說(shuō),應(yīng)該是最好理解也最容易使用的一個(gè)函數(shù)了。下面就此來(lái)舉幾個(gè)簡(jiǎn)單的例子:

復(fù)制代碼代碼如下:

#簡(jiǎn)單的findall

>>> re.findall('\w+', 'hello, world!')

['hello', 'world']

#這個(gè)返回的就是元組的列表

>>> re.findall('(\d+)\.(\d+)\.(\d+)\.(\d+)', 'My IP is 192.168.0.2, and your is 192.168.0.3.')

[('192', '168', '0', '2'), ('192', '168', '0', '3')]

re. finditer(pattern, string[, flags])

和上面的findall()類似,但返回的是MatchObject的實(shí)例的迭代器。

還是例子說(shuō)明問(wèn)題:

復(fù)制代碼代碼如下:

>>> for m in re.finditer('\w+', 'hello, world!'):

... print m.group()

...

hello

world

re.sub(pattern, repl, string[, count])

替換,將string里,匹配pattern的部分,用repl替換掉,最多替換count次(剩余的匹配將不做處理),然后返回替換后的字符串。如果string里沒有可以匹配pattern的串,將被原封不動(dòng)地返回。repl可以是一個(gè)字符串,也可以是一個(gè)函數(shù)(也可以參考我以前的例子)。如果repl是個(gè)字符串,則其中的反斜桿會(huì)被處理過(guò),比如 \n 會(huì)被轉(zhuǎn)成換行符,反斜桿加數(shù)字會(huì)被替換成相應(yīng)的組,比如 \6 表示pattern匹配到的第6個(gè)組的內(nèi)容。

例子:

復(fù)制代碼代碼如下:

>>> re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):',

...??????? r'static PyObject*\npy_\1(void)\n{',

...??????? 'def myfunc():')

'static PyObject*\npy_myfunc(void)\n{'

如果repl是個(gè)函數(shù),每次pattern被匹配到的時(shí)候,都會(huì)被調(diào)用一次,傳入一個(gè)匹配到的MatchObject對(duì)象,需要返回一個(gè)字符串,在匹配到的位置,就填入返回的字符串。

例子:

復(fù)制代碼代碼如下:

>>> def dashrepl(matchobj):

...???? if matchobj.group(0) == '-': return ' '

...???? else: return '-'

>>> re.sub('-{1,2}', dashrepl, 'pro----gram-files')

'pro--gram files'

零長(zhǎng)度的匹配也會(huì)被替換,比如:

復(fù)制代碼代碼如下:

>>> re.sub('x*', '-', 'abcxxd')

'-a-b-c-d-'

特殊地,在替換字符串里,如果有\(zhòng)g這樣的寫法,將匹配正則的命名組(前面介紹過(guò)的,(?P...)這樣定義出來(lái)的東西)。\g這樣的寫法,也是數(shù)字的組,也就是說(shuō),\g<2>一般和\2是等效的,但是萬(wàn)一你要在\2后面緊接著寫上字面意義的0,你就不能寫成\20了(因?yàn)檫@代表第20個(gè)組),這時(shí)候必須寫成\g<2>0,另外,\g<0>代表匹配到的整個(gè)子串。

例子:

復(fù)制代碼代碼如下:

>>> re.sub('-(\d+)-', '-\g<1>0\g<0>', 'a-11-b-22-c')

'a-110-11-b-220-22-c'

re.subn(pattern, repl, string[, count])

跟上面的sub()函數(shù)一樣,只是它返回的是一個(gè)元組 (新字符串, 匹配到的次數(shù))

,還是用例子說(shuō)話:

復(fù)制代碼代碼如下:

>>> re.subn('-(\d+)-', '-\g<1>0\g<0>', 'a-11-b-22-c')

('a-110-11-b-220-22-c', 2)

re.escape(string)

把string中,除了字母和數(shù)字以外的字符,都加上反斜桿。

復(fù)制代碼代碼如下:

>>> print re.escape('abc123_@#$')

abc123\_\@\#\$

exception re.error

如果字符串不能被成功編譯成正則表達(dá)式或者正則表達(dá)式在匹配過(guò)程中出錯(cuò)了,都會(huì)拋出此異常。但是如果正則表達(dá)式?jīng)]有匹配到任何文本,是不會(huì)拋出這個(gè)異常的。

正則對(duì)象

正則對(duì)象由re.compile()返回。它有如下的屬性和方法。

match(string[, pos[, endpos]])

作用和模塊的match()函數(shù)類似,區(qū)別就是后面兩個(gè)參數(shù)。

pos是開始搜索的位置,默認(rèn)為0。endpos是搜索的結(jié)束位置,如果endpos比pos還小的話,結(jié)果肯定是空的。也就是說(shuō)只有pos 到 endpos-1 位置的字符串將會(huì)被搜索。

例子:

復(fù)制代碼代碼如下:

>>> pattern = re.compile("o")

>>> pattern.match("dog")????? # 開始位置不是o,所以不匹配

>>> pattern.match("dog", 1)?? # 第二個(gè)字符是o,所以匹配

<_sre.SRE_Match object at ...>

search(string[, pos[, endpos]])

作用和模塊的search()函數(shù)類似,pos和endpos參數(shù)和上面的match()函數(shù)類似。

split(string[, maxsplit=0])

findall(string[, pos[, endpos]])

finditer(string[, pos[, endpos]])

sub(repl, string[, count=0])

subn(repl, string[, count=0])

這幾個(gè)函數(shù),都和模塊的相應(yīng)函數(shù)一致。

flags

編譯本RE時(shí),指定的標(biāo)志位,如果未指定任何標(biāo)志位,則為0。

復(fù)制代碼代碼如下:

>>> pattern = re.compile("o", re.S|re.U)

>>> pattern.flags

48

groups

RE所含有的組的個(gè)數(shù)。

groupindex

一個(gè)字典,定義了命名組的名字和序號(hào)之間的關(guān)系。

例子:這個(gè)正則有3個(gè)組,如果匹配到,第一個(gè)叫區(qū)號(hào),最后一個(gè)叫分機(jī)號(hào),中間的那個(gè)未命名

復(fù)制代碼代碼如下:

>>> pattern = re.compile("(?P\d+)-(\d+)-(?P\d+)")

>>> pattern.groups

3

>>> pattern.groupindex

{'fenjihao': 3, 'quhao': 1}

pattern

建立本RE的原始字符串,相當(dāng)于源代碼了,呵呵。

還是上面這個(gè)正則,可以看到,會(huì)原樣返回:

復(fù)制代碼代碼如下:

>>> print pattern.pattern

(?P\d+)-(\d+)-(?P\d+)

Match對(duì)象

re.MatchObject被用于布爾判斷的時(shí)候,始終返回True,所以你用 if 語(yǔ)句來(lái)判斷某個(gè) match() 是否成功是安全的。

它有以下方法和屬性:

expand(template)

用template做為模板,將MatchObject展開,就像sub()里的行為一樣,看例子:

復(fù)制代碼代碼如下:

>>> m = re.match('a=(\d+)', 'a=100')

>>> m.expand('above a is \g<1>')

'above a is 100'

>>> m.expand(r'above a is \1')

'above a is 100'

group([group1, ...])

返回一個(gè)或多個(gè)子組。如果參數(shù)為一個(gè),就返回一個(gè)子串;如果參數(shù)有多個(gè),就返回多個(gè)子串注冊(cè)的元組。如果不傳任何參數(shù),效果和傳入一個(gè)0一樣,將返回整個(gè)匹配。如果某個(gè)groupN未匹配到,相應(yīng)位置會(huì)返回None。如果某個(gè)groupN是負(fù)數(shù)或者大于group的總數(shù),則會(huì)拋出IndexError異常。

復(fù)制代碼代碼如下:

>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")

>>> m.group(0)?????? # 整個(gè)匹配

'Isaac Newton'

>>> m.group(1)?????? # 第一個(gè)子串

'Isaac'

>>> m.group(2)?????? # 第二個(gè)子串

'Newton'

>>> m.group(1, 2)??? # 多個(gè)子串組成的元組

('Isaac', 'Newton')

如果有其中有用(?P...)這種語(yǔ)法命名過(guò)的子串的話,相應(yīng)的groupN也可以是名字字符串。例如:

復(fù)制代碼代碼如下:

>>> m = re.match(r"(?P\w+) (?P\w+)", "Malcolm Reynolds")

>>> m.group('first_name')

'Malcolm'

>>> m.group('last_name')

'Reynolds'

如果某個(gè)組被匹配到多次,那么只有最后一次的數(shù)據(jù),可以被提取到:

復(fù)制代碼代碼如下:

>>> m = re.match(r"(..)+", "a1b2c3")? # 匹配到3次

>>> m.group(1)??????????????????????? # 返回的是最后一次

'c3'

groups([default])

返回一個(gè)由所有匹配到的子串組成的元組。default參數(shù),用于給那些沒有匹配到的組做默認(rèn)值,它的默認(rèn)值是None

例如:

復(fù)制代碼代碼如下:

>>> m = re.match(r"(\d+)\.(\d+)", "24.1632")

>>> m.groups()

('24', '1632')

default的作用:

復(fù)制代碼代碼如下:

>>> m = re.match(r"(\d+)\.?(\d+)?", "24")

>>> m.groups()????? # 第二個(gè)默認(rèn)是None

('24', None)

>>> m.groups('0')?? # 現(xiàn)在默認(rèn)是0了

('24', '0')

groupdict([default])

返回一個(gè)包含所有命名組的名字和子串的字典,default參數(shù),用于給那些沒有匹配到的組做默認(rèn)值,它的默認(rèn)值是None,例如:

復(fù)制代碼代碼如下:

>>> m = re.match(r"(?P\w+) (?P\w+)", "Malcolm Reynolds")

>>> m.groupdict()

{'first_name': 'Malcolm', 'last_name': 'Reynolds'}

start([group])

end([group])

返回的是:被組group匹配到的子串在原字符串中的位置。如果不指定group或group指定為0,則代表整個(gè)匹配。如果group未匹配到,則返回 -1。

對(duì)于指定的m和g,m.group(g)和m.string[m.start(g):m.end(g)]等效。

注意:如果group匹配到空字符串,m.start(group)和m.end(group)將相等。

例如:

復(fù)制代碼代碼如下:

>>> m = re.search('b(c?)', 'cba')

>>> m.start(0)

1

>>> m.end(0)

2

>>> m.start(1)

2

>>> m.end(1)

2

下面是一個(gè)把email地址里的“remove_this”去掉的例子:

復(fù)制代碼代碼如下:

>>> email = "tony@tiremove_thisger.net"

>>> m = re.search("remove_this", email)

>>> email[:m.start()] + email[m.end():]

'tony@tiger.net'

span([group])

返回一個(gè)元組: (m.start(group), m.end(group))

pos

就是傳給RE對(duì)象的search()或match()方法的參數(shù)pos,代表RE開始搜索字符串的位置。

endpos

就是傳給RE對(duì)象的search()或match()方法的參數(shù)endpos,代表RE搜索字符串的結(jié)束位置。

lastindex

最后一次匹配到的組的數(shù)字序號(hào),如果沒有匹配到,將得到None。

例如:(a)b、((a)(b))和((ab))正則去匹配'ab'的話,得到的lastindex為1。而用(a)(b)去匹配'ab'的話,得到的lastindex為2。

lastgroup

最后一次匹配到的組的名字,如果沒有匹配到或者最后的組沒有名字,將得到None。

re

得到本Match對(duì)象的正則表達(dá)式對(duì)象,也就是執(zhí)行search()或match()的對(duì)象。

string

傳給search()或match()的字符串。


最后附一個(gè)在線生成工具,可以把自己寫的表達(dá)式和生成的對(duì)比一下,看看自己有那些問(wèn)題喲

? ? ? ? ?(^U^)ノ~YO正則表達(dá)式在線工具


學(xué)習(xí)筆記,侵刪

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,283評(píng)論 6 530
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 97,947評(píng)論 3 413
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,094評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,485評(píng)論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,268評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,817評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,906評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,039評(píng)論 0 285
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,551評(píng)論 1 331
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,502評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,662評(píng)論 1 366
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,188評(píng)論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,907評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,304評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,563評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,255評(píng)論 3 389
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,637評(píng)論 2 370

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