Python中的正則表達(dá)式(re)

Python中的正則表達(dá)式(re)

<pre>import re
re.match #從開始位置開始匹配箱蟆,如果開頭沒有則無
re.search #搜索整個字符串
re.findall #搜索整個字符串,返回一個list</pre>

舉例:

<pre>r(raw)用在pattern之前刮便,表示單引號中的字符串為原生字符空猜,不會進(jìn)行任何轉(zhuǎn)義
re.match(r'l','liuyan1').group() #返回l
re.match(r'y','liuyan1') #返回None
re.search(r'y','liuyan1').group() #返回y</pre>

正則表達(dá)式可以包含一些可選標(biāo)志修飾符來控制匹配的模式。修飾符被指定為一個可選的標(biāo)志。多個標(biāo)志可以通過按位 OR(|) 它們來指定辈毯。如 re.I | re.M 被設(shè)置成 I 和 M 標(biāo)志:

| 修飾符 | 描述 |
| re.I | 使匹配對大小寫不敏感 |
| re.L | 做本地化識別(locale-aware)匹配 |
| re.M | 多行匹配坝疼,影響 ^ 和 $ |
| re.S | 使 . 匹配包括換行在內(nèi)的所有字符 |
| re.U | 根據(jù)Unicode字符集解析字符。這個標(biāo)志影響 \w, \W, \b, \B. |
| re.X | 該標(biāo)志通過給予你更靈活的格式以便你將正則表達(dá)式寫得更易于理解谆沃。 |

<pre>re.search(r'[a-z]+','liuyaN1234ab9').group() #返回'liuya'
re.search(r'[a-z]+','liuyaN1234ab9', re.I).group() #返回'liuyaN'钝凶,對大小寫不敏感</pre>

<pre>#如果匹配成功,則打印m管毙,否則返回Null
if re.match(r'[0-9]','a'):print 'm'</pre>

<pre>#用空格分割
re.split(r'\s+', 'a b c')
返回:['a', 'b', 'c', 'd']</pre>

<pre>#用逗號分隔
re.split(r'[\s,]+', 'a,b, c d')
返回:['a', 'b', 'c', 'd']</pre>

rr=re.match(r'[0-9]','3')

rr.group(0)

正則表達(dá)式模式--http://www.runoob.com/python/python-reg-expressions.html

模式字符串使用特殊的語法來表示一個正則表達(dá)式:

字母和數(shù)字表示他們自身腿椎。一個正則表達(dá)式模式中的字母和數(shù)字匹配同樣的字符串。

多數(shù)字母和數(shù)字前加一個反斜杠時會擁有不同的含義夭咬。

標(biāo)點(diǎn)符號只有被轉(zhuǎn)義時才匹配自身,否則它們表示特殊的含義铆隘。

反斜杠本身需要使用反斜杠轉(zhuǎn)義卓舵。

由于正則表達(dá)式通常都包含反斜杠,所以你最好使用原始字符串來表示它們膀钠。模式元素(如 r'/t'掏湾,等價于'//t')匹配相應(yīng)的特殊字符。

下表列出了正則表達(dá)式模式語法中的特殊元素肿嘲。如果你使用模式的同時提供了可選的標(biāo)志參數(shù)融击,某些模式元素的含義會改變。

| 模式 | 描述 |
| ^ | 匹配字符串的開頭 |
| $ | 匹配字符串的末尾雳窟。 |
| . | 匹配任意字符尊浪,除了換行符,當(dāng)re.DOTALL標(biāo)記被指定時封救,則可以匹配包括換行符的任意字符拇涤。 |
| [...] | 用來表示一組字符,單獨(dú)列出:[amk] 匹配 'a','m'或'k' |
| [^...] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符誉结。 |
| re* | 匹配0個或多個的表達(dá)式鹅士。 |
| re+ | 匹配1個或多個的表達(dá)式。 |
| re? | 匹配0個或1個由前面的正則表達(dá)式定義的片段惩坑,非貪婪方式 |
| re{ n} | |
| re{ n,} | 精確匹配n個前面表達(dá)式掉盅。 |
| re{ n, m} | 匹配 n 到 m 次由前面的正則表達(dá)式定義的片段,貪婪方式 |
| a| b | 匹配a或b |
| (re) | G匹配括號內(nèi)的表達(dá)式以舒,也表示一個組 |
| (?imx) | 正則表達(dá)式包含三種可選標(biāo)志:i, m, 或 x 趾痘。只影響括號中的區(qū)域。 |
| (?-imx) | 正則表達(dá)式關(guān)閉 i, m, 或 x 可選標(biāo)志稀轨。只影響括號中的區(qū)域笙纤。 |
| (?: re) | 類似 (...), 但是不表示一個組 |
| (?imx: re) | 在括號中使用i, m, 或 x 可選標(biāo)志 |
| (?-imx: re) | 在括號中不使用i, m, 或 x 可選標(biāo)志 |
| (?#...) | 注釋. |
| (?= re) | 前向肯定界定符。如果所含正則表達(dá)式灸促,以 ... 表示,在當(dāng)前位置成功匹配時成功艰赞,否則失敗。但一旦所含表達(dá)式已經(jīng)嘗試肚吏,匹配引擎根本沒有提高方妖;模式的剩余部分還要嘗試界定符的右邊。 |
| (?! re) | 前向否定界定符罚攀。與肯定界定符相反党觅;當(dāng)所含表達(dá)式不能在字符串當(dāng)前位置匹配時成功 |
| (?> re) | 匹配的獨(dú)立模式,省去回溯斋泄。 |
| \w | 匹配字母數(shù)字 |
| \W | 匹配非字母數(shù)字 |
| \s | 匹配任意空白字符杯瞻,等價于 [\t\n\r\f]. |
| \S | 匹配任意非空字符 |
| \d | 匹配任意數(shù)字,等價于 [0-9]. |
| \D | 匹配任意非數(shù)字 |
| \A | 匹配字符串開始 |
| \Z | 匹配字符串結(jié)束炫掐,如果是存在換行魁莉,只匹配到換行前的結(jié)束字符串。c |
| \z | 匹配字符串結(jié)束 |
| \G | 匹配最后匹配完成的位置募胃。 |
| \b | 匹配一個單詞邊界旗唁,也就是指單詞和空格間的位置。例如痹束, 'er\b' 可以匹配"never" 中的 'er'检疫,但不能匹配 "verb" 中的 'er'。 |
| \B | 匹配非單詞邊界祷嘶。'er\B' 能匹配 "verb" 中的 'er'屎媳,但不能匹配 "never" 中的 'er'。 |
| \n, \t, 等. | 匹配一個換行符抹蚀。匹配一個制表符剿牺。等 |
| \1...\9 | 匹配第n個分組的子表達(dá)式。 |
| \10 | 匹配第n個分組的子表達(dá)式环壤,如果它經(jīng)匹配晒来。否則指的是八進(jìn)制字符碼的表達(dá)式。 |


正則表達(dá)式實(shí)例

字符匹配

| 實(shí)例 | 描述 |
| python | 匹配 "python". |

字符類

| 實(shí)例 | 描述 |
| [Pp]ython | 匹配 "Python" 或 "python" |
| rub[ye] | 匹配 "ruby" 或 "rube" |
| [aeiou] | 匹配中括號內(nèi)的任意一個字母 |
| [0-9] | 匹配任何數(shù)字郑现。類似于 [0123456789] |
| [a-z] | 匹配任何小寫字母 |
| [A-Z] | 匹配任何大寫字母 |
| [a-zA-Z0-9] | 匹配任何字母及數(shù)字 |
| [^aeiou] | 除了aeiou字母以外的所有字符 |
| [^0-9] | 匹配除了數(shù)字外的字符 |

特殊字符類

| 實(shí)例 | 描述 |
| . | 匹配除 "\n" 之外的任何單個字符湃崩。要匹配包括 '\n' 在內(nèi)的任何字符,請使用象 '[.\n]' 的模式接箫。 |
| \d | 匹配一個數(shù)字字符攒读。等價于 [0-9]。 |
| \D | 匹配一個非數(shù)字字符辛友。等價于 [^0-9]薄扁。 |
| \s | 匹配任何空白字符剪返,包括空格、制表符邓梅、換頁符等等脱盲。等價于 [ \f\n\r\t\v]。 |
| \S | 匹配任何非空白字符日缨。等價于 [^ \f\n\r\t\v]钱反。 |
| \w | 匹配包括下劃線的任何單詞字符。等價于'[A-Za-z0-9_]'匣距。 |
| \W | 匹配任何非單詞字符面哥。等價于 '[^A-Za-z0-9_]'。 |

1 Python ****正則式的基本用法 --原文地址:http://blog.csdn.net/whycadi/archive/2008/01/02/2011046.aspx

Python 的正則表達(dá)式的模塊是 ‘re’, 它的基本語法規(guī)則就是指定一個字符序列毅待,比如你要在一個字符串 s=’123abc456’ 中查找字符串 ’abc’, 只要這樣寫:

import re

s='123abc456eabc789'

re.findall(r’abc’,s)

結(jié)果就是:

['abc', 'abc']

這里用到的函數(shù) ”findall(rule , target [,flag] )” 是個比較直觀的函數(shù)尚卫,就是在目標(biāo)字符串中查找符合規(guī)則的字符串。第一個參數(shù)是規(guī)則恩静,第二個參數(shù)是目標(biāo)字符串焕毫,后面還可以跟一個規(guī)則選項(xiàng)(選項(xiàng)功能將在 compile 函數(shù)的說明中詳細(xì)說明)。返回結(jié)果結(jié)果是一個列表驶乾, 中間存放的是符合規(guī)則的字符串。如果沒有符合規(guī)則的字符串被找到循签,就返回一個 列表级乐。

為什么要用 ****r’ ..‘ ****字符串( ****raw ****字符串)? ****由于正則式的規(guī)則也是由一個字符串定義的县匠,而在正則式中大量使用轉(zhuǎn)義字符 ****’/’ ****风科,如果不用 ****raw ****字符串,則在需要寫一個 ****’/’ ****的地方乞旦,你必須得寫成 ****’//’, ****那么在要從目標(biāo)字符串中匹配一個 ****’/’ ****的時候贼穆,你就得寫上 ****4 ****個 ****’/’ ****成為 ****’////’ ****!這當(dāng)然很麻煩兰粉,也不直觀故痊,所以一般都使用 ****r’’ ****來定義規(guī)則字符串。當(dāng)然玖姑,某些情況下愕秫,可能不用 ****raw ****字符串比較好。

以上是個最簡單的例子焰络。當(dāng)然實(shí)際中這么簡單的用法幾乎沒有意義戴甩。為了實(shí)現(xiàn)復(fù)雜的規(guī)則查找, re 規(guī)定了若干語法規(guī)則闪彼。它們分為這么幾類:

功能字符 : ‘.’ ‘*’ ‘+’ ‘|’ ‘?’ ‘^’ ‘$’ ‘/’ 等甜孤,它們有特殊的功能含義。特別是 ’/’ 字符,它是轉(zhuǎn)義引導(dǎo)符號缴川,跟在它后面的字符一般有特殊的含義茉稠。

規(guī)則分界符: ‘[‘ ‘]’ ‘ ( ’ ‘ ) ’ ‘{‘ ‘}’ 等,也就是幾種括號了二跋。

預(yù)定義轉(zhuǎn)義字符集: “/d” “/w” “/s” 等等战惊,它們是以字符 ’/’ 開頭,后面接一個特定字符的形式扎即,用來指示一個預(yù)定義好的含義吞获。

其它特殊功能字符: ’#’ ‘!’ ‘:’ ‘-‘ 等,它們只在特定的情況下表示特殊的含義谚鄙,比如 (?# …) 就表示一個注釋各拷,里面的內(nèi)容會被忽略。

下面來一個一個的說明這些規(guī)則的含義闷营,不過說明的順序并不是按照上面的順序來的烤黍,而是我認(rèn)為由淺入深,由基本到復(fù)雜的順序來編排的傻盟。同時為了直觀速蕊,在說明的過程中盡量多舉些例子以方便理解。

1.1 ****基本規(guī)則

‘[‘ ‘]’ ****字符集合設(shè)定符

首先說明一下字符集合設(shè)定的方法娘赴。由一對方括號括起來的字符规哲,表明一個字符集合,能夠匹配包含在其中的任意一個字符诽表。比如 [abc123] 唉锌,表明字符 ’a’ ‘b’ ‘c’ ‘1’ ‘2’ ‘3’ 都符合它的要求「妥啵可以被匹配袄简。

在 ’[‘ ‘]’ 中還可以通過 ’-‘ 減號來指定一個字符集合的范圍,比如可以用 [a-zA-Z] 來指定所以英文字母的大小寫泛啸,因?yàn)橛⑽淖帜甘前凑諒男〉酱蟮捻樞騺砼诺穆逃铩D悴豢梢园汛笮〉捻樞蝾嵉沽耍热鐚懗?[z-a] 就不對了平痰。

如果在 ’[‘ ‘]’ 里面的開頭寫一個 ‘^’ 號汞舱,則表示取非,即在括號里的字符都不匹配宗雇。如 [^a-zA-Z] 表明不匹配所有英文字母昂芜。但是如果 ‘^’ 不在開頭,則它就不再是表示取非赔蒲,而表示其本身泌神,如 [a-z^A-Z] 表明匹配所有的英文字母和字符 ’^’ 良漱。

‘|’ ****或規(guī)則

將兩個規(guī)則并列起來,以‘ | ’連接欢际,表示只要滿足其中之一就可以匹配母市。比如

[a-zA-Z]|[0-9] 表示滿足數(shù)字或字母就可以匹配,這個規(guī)則等價于 [a-zA-Z0-9]

**注意 **:關(guān)于 ’|’ 要注意兩點(diǎn):

第一损趋, 它在 ’[‘ ‘]’ 之中不再表示或患久,而表示他本身的字符。如果要在 ’[‘ ‘]’ 外面表示一個 ’|’ 字符浑槽,必須用反斜杠引導(dǎo)蒋失,即 ’/|’ ;

第二, 它的有效范圍是它兩邊的整條規(guī)則桐玻,比如‘ dog|cat’ 匹配的是‘ dog’ 和 ’cat’ 篙挽,而不是 ’g’ 和 ’c’ 。如果想限定它的有效范圍镊靴,必需使用一個無捕獲組 ‘(?: )’ 包起來铣卡。比如要匹配 ‘ I have a dog’ 或 ’I have a cat’ ,需要寫成 r’I have a (?:dog|cat)’ 偏竟,而不能寫成 r’I have a dog|cat’

s = ‘I have a dog , I have a cat’

re.findall( r’I have a (?:dog|cat)’ , s )

['I have a dog', 'I have a cat'] # 正如我們所要的

下面再看看不用無捕獲組會是什么后果:

re.findall( r’I have a dog|cat’ , s )

['I have a dog', 'cat'] # 它將 ’I have a dog’ 和 ’cat’ 當(dāng)成兩個規(guī)則了

至于無捕獲組的使用煮落,后面將仔細(xì)說明。這里先跳過踊谋。

‘.’ ****匹配所有字符

匹配除換行符 ’/n’ 外的所有字符州邢。如果使用了 ’S’ 選項(xiàng),匹配包括 ’/n’ 的所有字符褪子。

   例:

   >>> s=’123 /n456 /n789’

   >>> findall(r‘.+’,s)

   ['123', '456', '789']

   >>> re.findall(r‘.+’ , s , re.S)

   ['123/n456/n789']

‘^’ ****和 ’$’ ****匹配字符串開頭和結(jié)尾

注意 ’^’ 不能在‘ [ ] ’中,否則含意就發(fā)生變化骗村,具體請看上面的 ’[‘ ‘]’ 說明嫌褪。 在多行模式下,它們可以匹配每一行的行首和行尾胚股。具體請看后面 compile 函數(shù)說明的 ’M’ 選項(xiàng)部分

‘/d’ ****匹配數(shù)字

這是一個以 ’/’ 開頭的轉(zhuǎn)義字符笼痛, ’/d’ 表示匹配一個數(shù)字,即等價于 [0-9]

‘/D’ ****匹配非數(shù)字

這個是上面的反集琅拌,即匹配一個非數(shù)字的字符缨伊,等價于 [^0-9] 。注意它們的大小寫进宝。下面我們還將看到 Python 的正則規(guī)則中很多轉(zhuǎn)義字符的大小寫形式刻坊,代表互補(bǔ)的關(guān)系。這樣很好記党晋。

‘/w’ ****匹配字母和數(shù)字

匹配所有的英文字母和數(shù)字谭胚,即等價于 [a-zA-Z0-9] 徐块。

‘/W’ ****匹配非英文字母和數(shù)字

即 ’/w’ 的補(bǔ)集,等價于 [^a-zA-Z0-9] 灾而。

‘/s’ ****匹配間隔符

即匹配空格符胡控、制表符、回車符等表示分隔意義的字符旁趟,它等價于 [ /t/r/n/f/v] 昼激。(注意最前面有個空格 )

‘/S’ ****匹配非間隔符

即間隔符的補(bǔ)集,等價于 [^ /t/r/n/f/v]

‘/A’ ****匹配字符串開頭

匹配字符串的開頭锡搜。它和 ’^’ 的區(qū)別是橙困, ’/A’ 只匹配整個字符串的開頭,即使在 ’M’ 模式下余爆,它也不會匹配其它行的很首纷宇。

‘/Z’ ****匹配字符串結(jié)尾

匹配字符串的結(jié)尾。它和 ’$’ 的區(qū)別是蛾方, ’/Z’ 只匹配整個字符串的結(jié)尾像捶,即使在 ’M’ 模式下,它也不會匹配其它各行的行尾桩砰。

例:

s= '12 34/n56 78/n90'

re.findall( r'^/d+' , s , re.M ) # 匹配位于行首的數(shù)字

['12', '56', '90']

re.findall( r’/A/d+’, s , re.M ) # 匹配位于字符串開頭的數(shù)字

['12']

re.findall( r'/d+$' , s , re.M ) # 匹配位于行尾的數(shù)字

['34', '78', '90']

re.findall( r’/d+/Z’ , s , re.M ) # 匹配位于字符串尾的數(shù)字

['90']

‘/b’ ****匹配單詞邊界

它匹配一個單詞的邊界拓春,比如空格等,不過它是一個‘ 0 ’長度字符亚隅,它匹配完的字符串不會包括那個分界的字符硼莽。而如果用 ’/s’ 來匹配的話,則匹配出的字符串中會包含那個分界符煮纵。

例:

s = 'abc abcde bc bcd'

re.findall( r’/bbc/b’ , s ) # 匹配一個單獨(dú)的單詞 ‘bc’ 懂鸵,而當(dāng)它是其它單詞的一部分的時候不匹配

['bc'] #只找到了那個單獨(dú)的 ’bc’

re.findall( r’/sbc/s’ , s ) #匹配一個單獨(dú)的單詞 ‘bc’

[' bc '] # 只找到那個單獨(dú)的 ’bc’ ,不過注意前后有兩個空格行疏,可能有點(diǎn)看不清楚

‘/B’ ****匹配非邊界

和 ’/b’ 相反匆光,它只匹配非邊界的字符。它同樣是個 0 長度字符酿联。

接上例:

re.findall( r’/Bbc/w+’ , s ) # 匹配包含 ’bc’ 但不以 ’bc’ 為開頭的單詞

['bcde'] # 成功匹配了 ’abcde’ 中的 ’bcde’ 终息,而沒有匹配 ’bcd’

‘(?:)’ ****無捕獲組

當(dāng)你要將一部分規(guī)則作為一個整體對它進(jìn)行某些操作,比如指定其重復(fù)次數(shù)時贞让,你需要將這部分規(guī)則用 ’(?:’ ‘)’ 把它包圍起來周崭,而不能僅僅只用一對括號,那樣將得到絕對出人意料的結(jié)果喳张。

例:匹配字符串中重復(fù)的 ’ab’

s=’ababab abbabb aabaab’

re.findall( r’/b(?:ab)+/b’ , s )

['ababab']

如果僅使用一對括號续镇,看看會是什么結(jié)果:

re.findall( r’/b(ab)+/b’ , s )

['ab']

這是因?yàn)槿绻皇褂靡粚ㄌ枺敲催@就成為了一個組 (group) 蹲姐。組的使用比較復(fù)雜磨取,將在后面詳細(xì)講解人柿。

‘(?# )’ ****注釋

Python 允許你在正則表達(dá)式中寫入注釋,在 ’(?#’ ‘)’ 之間的內(nèi)容將被忽略忙厌。

**(?iLmsux) **``**編譯選項(xiàng)指定**

Python 的正則式可以指定一些選項(xiàng)凫岖,這個選項(xiàng)可以寫在 findall 或 compile 的參數(shù)中,也可以寫在正則式里逢净,成為正則式的一部分哥放。這在某些情況下會便利一些。具體的選項(xiàng)含義請看后面的 compile 函數(shù)的說明爹土。

此處編譯選項(xiàng) ’i’ 等價于 IGNORECASE 甥雕,L 等價于 LOCAL ,m 等價于 MULTILINE 胀茵, s 等價于 DOTALL 社露, u 等價于 UNICODE , x 等價于 VERBOSE 琼娘。

請注意它們的大小寫峭弟。在使用時可以只指定一部分,比如只指定忽略大小寫脱拼,可寫為 ‘(?i)’ 瞒瘸,要同時忽略大小寫并使用多行模式,可以寫為 ‘(?im)’ 熄浓。

另外要注意選項(xiàng)的有效范圍是整條規(guī)則情臭,即寫在規(guī)則的任何地方,選項(xiàng)都會對全部整條正則式有效赌蔑。

1.2 ****重復(fù)

正則式需要匹配不定長的字符串俯在,那就一定需要表示重復(fù)的指示符。 Python 的正則式表示重復(fù)的功能很豐富靈活娃惯。重復(fù)規(guī)則的一般的形式是在一條字符規(guī)則后面緊跟一個表示重復(fù)次數(shù)的規(guī)則朝巫,已表明需要重復(fù)前面的規(guī)則一定的次數(shù)。重復(fù)規(guī)則有:

’ 0 ****或多次匹配*

表示匹配前面的規(guī)則 0 次或多次石景。

‘+’ 1 ****次或多次匹配

表示匹配前面的規(guī)則至少 1 次,可以多次匹配

例:匹配以下字符串中的前一部分是字母拙吉,后一部分是數(shù)字或沒有的變量名字

s = ‘ aaa bbb111 cc22cc 33dd ‘

re.findall( r’/b[a-z]+/d*/b’ , s ) # 必須至少 1 個字母開頭潮孽,以連續(xù)數(shù)字結(jié)尾或沒有數(shù)字

['aaa', 'bbb111']

注意上例中規(guī)則前后加了表示單詞邊界的 ’/b’ 指示符,如果不加的話結(jié)果就會變成:

re.findall( r’[a-z]+/d*’ , s )

['aaa', 'bbb111', 'cc22', 'cc', 'dd'] # 把單詞給拆開了

大多數(shù)情況下這不是我們期望的結(jié)果筷黔。

‘?’ 0 ****或 1 ****次匹配

只匹配前面的規(guī)則 0 次或 1 次往史。

例,匹配一個數(shù)字佛舱,這個數(shù)字可以是一個整數(shù)椎例,也可以是一個科學(xué)計(jì)數(shù)法記錄的數(shù)字挨决,比如 123 和 10e3 都是正確的數(shù)字。

s = ‘ 123 10e3 20e4e4 30ee5 ‘

re.findall( r’ /b/d+[eE]?/d*/b’ , s )

['123', '10e3']

它正確匹配了 123 和 10e3, 正是我們期望的订歪。注意前后的 ’/b’ 的使用脖祈,否則將得到不期望的結(jié)果。

1.2.1 ****精確匹配和最小匹配

Python 正則式還可以精確指定匹配的次數(shù)刷晋。指定的方式是

‘{m}’ ****精確匹配 m ****次

‘{m,n}’ ****匹配最少 m ****次盖高,最多 n ****次。 (n>m)

如果你只想指定一個最少次數(shù)或只指定一個最多次數(shù)眼虱,你可以把另外一個參數(shù)空起來喻奥。比如你想指定最少 3 次,可以寫成 {3,} (注意那個逗號)捏悬,同樣如果只想指定最大為 5 次撞蚕,可以寫成 { , 5} 过牙,也可以寫成 {0,5} 甥厦。

例 尋找下面字符串中

a : 3 位數(shù)

b: 2 位數(shù)到 4 位數(shù)

c: 5 位數(shù)以上的數(shù)

d: 4 位數(shù)以下的數(shù)

s= ‘ 1 22 333 4444 55555 666666 ‘

re.findall( r’/b/d{3}/b’ , s ) # a : 3 位數(shù)

['333']

re.findall( r’/b/d{2,4}/b’ , s ) # b: 2 位數(shù)到 4 位數(shù)

['22', '333', '4444']

re.findall( r’/b/d{5,}/b’, s ) # c: 5 位數(shù)以上的數(shù)

['55555', '666666']

re.findall( r’/b/d{1,4}/b’ , s ) # 4 位數(shù)以下的數(shù)

['1', '22', '333', '4444']

?’ ‘+?’ ‘??’ ****最小匹配*

’ ‘+’ ‘?’ 通常都是盡可能多的匹配字符。有時候我們希望它盡可能少的匹配抒和。比如一個 c 語言的注釋 ‘/ part 1 / / part 2 */’ 矫渔,如果使用最大規(guī)則:

s =r ‘/* part 1 / code / part 2 */’

re.findall( r’//./*/’ , s )

[‘/* part 1 / code / part 2 */’]

結(jié)果把整個字符串都包括進(jìn)去了。如果把規(guī)則改寫成

re.findall( r’//.?/*/’ , s ) # 在 * 后面加上 ? 摧莽,表示盡可能少的匹配

['/* part 1 /', '/ part 2 */']

結(jié)果正確的匹配出了注釋里的內(nèi)容

1.3 ****前向界定與后向界定

有時候需要匹配一個跟在特定內(nèi)容后面的或者在特定內(nèi)容前面的字符串庙洼, Python 提供一個簡便的前向界定和后向界定功能,或者叫前導(dǎo)指定和跟從指定功能镊辕。它們是:

‘(?<=…)’ ****前向界定

括號中 ’…’ 代表你希望匹配的字符串的前面應(yīng)該出現(xiàn)的字符串油够。

‘(?=…)’ ****后向界定

括號中的 ’…’ 代表你希望匹配的字符串后面應(yīng)該出現(xiàn)的字符串。

例: 你希望找出 c 語言的注釋中的內(nèi)容征懈,它們是包含在 ’/’ 和 ’/’ 之間石咬,不過你并不希望匹配的結(jié)果把 ’/’ 和 ’/’ 也包括進(jìn)來,那么你可以這樣用:

s=r’/* comment 1 / code / comment 2 */’

re.findall( r’(?<=//).+?(?=//)’ , s )

[' comment 1 ', ' comment 2 ']

注意這里我們?nèi)匀皇褂昧俗钚∑ヅ渎舭ィ员苊獍颜麄€字符串給匹配進(jìn)去了鬼悠。

要注意的是,前向界定括號中的表達(dá)式必須是常值亏娜,也即你不可以在前向界定的括號里寫正則式焕窝。比如你如果在下面的字符串中想找到被字母夾在中間的數(shù)字,你不可以用前向界定:

例:

s = ‘a(chǎn)aa111aaa , bbb222 , 333ccc ‘

re.findall( r’(?<=[a-z]+)/d+(?=[a-z]+)' , s ) # 錯誤的用法

它會給出一個錯誤信息:

error: look-behind requires fixed-width pattern

不過如果你只要找出后面接著有字母的數(shù)字维贺,你可以在后向界定寫正則式:

re.findall( r’/d+(?=[a-z]+)’, s )

['111', '333']

如果你一定要匹配包夾在字母中間的數(shù)字它掂,你可以使用組( group )的方式

re.findall (r'[a-z]+(/d+)[a-z]+' , s )

['111']

組的使用將在后面詳細(xì)講解。

除了前向界定前向界定和后向界定外溯泣,還有前向非界定和后向非界定虐秋,它的寫法為:

**‘(?<!...)’ **``**前向非界定**

只有當(dāng)你希望的字符串前面不是’…’ 的內(nèi)容時才匹配

**‘(?!...)’ **``**后向非界定**

只有當(dāng)你希望的字符串后面不跟著 ’…’ 內(nèi)容時才匹配榕茧。

接上例,希望匹配后面不跟著字母的數(shù)字

re.findall( r’/d+(?!/w+)’ , s )

['222']

注意這里我們使用了 /w 而不是像上面那樣用 [a-z] 客给,因?yàn)槿绻@樣寫的話用押,結(jié)果會是:

re.findall( r’/d+(?![a-z]+)’ , s )

['11', '222', '33']

這和我們期望的似乎有點(diǎn)不一樣。它的原因起愈,是因?yàn)?’111’ 和 ’222’ 中的前兩個數(shù)字也是滿足這個要求的只恨。因此可看出,正則式的使用還是要相當(dāng)小心的抬虽,因?yàn)槲议_始就是這樣寫的官觅,看到結(jié)果后才明白過來。不過 Python 試驗(yàn)起來很方便阐污,這也是腳本語言的一大優(yōu)點(diǎn)休涤,可以一步一步的試驗(yàn),快速得到結(jié)果笛辟,而不用經(jīng)過煩瑣的編譯功氨、鏈接過程。也因此學(xué)習(xí) Python 就要多試手幢,跌跌撞撞的走過來捷凄,雖然曲折,卻也很有樂趣围来。

1.4 ****組的基本知識

上面我們已經(jīng)看過了 Python 的正則式的很多基本用法跺涤。不過如果僅僅是上面那些規(guī)則的話,還是有很多情況下會非常麻煩监透,比如上面在講前向界定和后向界定時桶错,取夾在字母中間的數(shù)字的例子。用前面講過的規(guī)則都很難達(dá)到目的胀蛮,但是用了組以后就很簡單了院刁。

‘(‘’)’ ****無命名組

最基本的組是由一對圓括號括起來的正則式。比如上面匹配包夾在字母中間的數(shù)字的例子中使用的 (/d+) 粪狼,我們再回顧一下這個例子:

s = ‘a(chǎn)aa111aaa , bbb222 , 333ccc ‘

re.findall (r'[a-z]+(/d+)[a-z]+' , s )

['111']

可以看到 findall ****函數(shù)只返回了包含在 ’()’ ****中的內(nèi)容退腥,而雖然前面和后面的內(nèi)容都匹配成功了,卻并不包含在結(jié)果中再榄。

除了最基本的形式外阅虫,我們還可以給組起個名字,它的形式是

‘(?P<name>…)’ ****命名組

‘(?P’ 代表這是一個 Python 的語法擴(kuò)展 ’<…>’ 里面是你給這個組起的名字不跟,比如你可以給一個全部由數(shù)字組成的組叫做 ’num’ ,它的形式就是 ’(?P<num>/d+)’ 米碰。起了名字之后窝革,我們就可以在后面的正則式中通過名字調(diào)用這個組购城,它的形式是

‘(?P=name)’ ****調(diào)用已匹配的命名組

要注意,再次調(diào)用的這個組是已被匹配的組虐译,也就是說它里面的內(nèi)容是和前面命名組里的內(nèi)容是一樣的瘪板。

我們可以看更多的例子:請注意下面這個字符串各子串的特點(diǎn)。

s='aaa111aaa,bbb222,333ccc,444ddd444,555eee666,fff777ggg'

我們看看下面的正則式會返回什么樣的結(jié)果:

re.findall( r'([a-z]+)/d+([a-z]+)' , s ) # 找出中間夾有數(shù)字的字母

[('aaa', 'aaa'), ('fff', 'ggg')]

re.findall( r '(?P<g1>[a-z]+)/d+(?P=g1)' , s ) # 找出被中間夾有數(shù)字的前后同樣的字母

['aaa']

re.findall( r'[a-z]+(/d+)([a-z]+)' , s ) # 找出前面有字母引導(dǎo)漆诽,中間是數(shù)字侮攀,后面是字母的字符串中的中間的數(shù)字和后面的字母

[('111', 'aaa'), ('777', 'ggg')]

我們可以通過命名組的名字在后面調(diào)用已匹配的命名組,不過名字也不是必需的厢拭。

‘/number’ ****通過序號調(diào)用已匹配的組

正則式中的每個組都有一個序號兰英,序號是按組從左到右,從 1 開始的數(shù)字供鸠,你可以通過下面的形式來調(diào)用已匹配的組

比如上面找出被中間夾有數(shù)字的前后同樣的字母的例子畦贸,也可以寫成:

re.findall( r’([a-z]+)/d+/1’ , s )

['aaa']

結(jié)果是一樣的。

我們再看一個例子

s='111aaa222aaa111 , 333bbb444bb33'

re.findall( r'(/d+)([a-z]+)(/d+)(/2)(/1)' , s ) # 找出完全對稱的 數(shù)字-字母-數(shù)字-字母-數(shù)字 中的數(shù)字和字母

[('111', 'aaa', '222', 'aaa', '111')]

Python2.4 以后的 re 模塊楞捂,還加入了一個新的條件匹配功能

**‘(?( **<var>**id/name **</var>**)yes-pattern|no-pattern)’ **``**判斷指定組是否已匹配薄坏,執(zhí)行相應(yīng)的規(guī)則**

這個規(guī)則的含義是,如果 id/name 指定的組在前面匹配成功了寨闹,則執(zhí)行 yes-pattern 的正則式胶坠,否則執(zhí)行 no-pattern 的正則式。

舉個例子繁堡,比如要匹配一些形如 usr@mail 的郵箱地址沈善,不過有的寫成 < usr@mail > 即用一對 <> 括起來,有點(diǎn)則沒有帖蔓,要匹配這兩種情況矮瘟,可以這樣寫

s='usr1@mail1 usr2@maill2'

re.findall( r'(<)?/s(/w+@/w+)/s(?(1)>)' , s )

[('<', 'usr1@mail1'), ('', 'usr2@maill2')]

不過如果目標(biāo)字符串如下

s='usr1@mail1 usr2@maill2 <usr3@mail3 usr4@mail4> < usr5@mail5 '

而你想得到要么由一對 <> 包圍起來的一個郵件地址,要么得到一個沒有被 <> 包圍起來的地址塑娇,但不想得到一對 <> 中間包圍的多個地址或不完整的 <> 中的地址澈侠,那么使用這個式子并不能得到你想要的結(jié)果

re.findall( r'(<)?/s(/w+@/w+)/s(?(1)>)' , s )

[('<', 'usr1@mail1'), ('', 'usr2@maill2'), ('', 'usr3@mail3'), ('', 'usr4@mail4'), ('', 'usr5@mail5')]

它仍然找到了所有的郵件地址。

想要實(shí)現(xiàn)這個功能埋酬,單純的使用 findall 有點(diǎn)吃力哨啃,需要使用其它的一些函數(shù),比如 match 或 search 函數(shù)写妥,再配合一些控制功能拳球。這部分的內(nèi)容將在下面詳細(xì)講解。

小結(jié):以上基本上講述了 Python 正則式的語法規(guī)則珍特。雖然大部分語法規(guī)則看上去都很簡單祝峻,可是稍不注意,仍然會得到與期望大相徑庭的結(jié)果,所以要寫好正則式莱找,需要仔細(xì)的體會正則式規(guī)則的含義后不同規(guī)則之間細(xì)微的差別酬姆。

詳細(xì)的了解了規(guī)則后,再配合后面就要介紹的功能函數(shù)奥溺,就能最大的發(fā)揮正則式的威力了辞色。

2 re ****模塊的基本函數(shù)

在上面的說明中,我們已經(jīng)對 re 模塊的基本函數(shù) ‘findall’ 很熟悉了浮定。當(dāng)然如果光有 findall 的話相满,很多功能是不能實(shí)現(xiàn)的。下面開始介紹一下 re 模塊其它的常用基本函數(shù)桦卒。靈活搭配使用這些函數(shù)立美,才能充分發(fā)揮 Python 正則式的強(qiáng)大功能。

首先還是說下老熟人 findall 函數(shù)吧

findall(rule , target [,flag] )

在目標(biāo)字符串中查找符合規(guī)則的字符串闸盔。

第一個參數(shù)是規(guī)則萝风,第二個參數(shù)是目標(biāo)字符串抚垃,后面還可以跟一個規(guī)則選項(xiàng)(選項(xiàng)功能將在 compile 函數(shù)的說明中詳細(xì)說明)哺壶。

返回結(jié)果結(jié)果是一個列表精偿, 中間存放的是符合規(guī)則的字符串。如果沒有符合規(guī)則的字符串被找到击费,就返回一個 列表拢蛋。

2.1 ****使用 compile ****加速

compile( rule [,flag] )

將正則規(guī)則編譯成一個 Pattern 對象,以供接下來使用蔫巩。

第一個參數(shù)是規(guī)則式谆棱,第二個參數(shù)是規(guī)則選項(xiàng)。

返回一個 Pattern 對象

直接使用 findall ( rule , target ) 的方式來匹配字符串圆仔,一次兩次沒什么垃瞧,如果是多次使用的話,由于正則引擎每次都要把規(guī)則解釋一遍坪郭,而規(guī)則的解釋又是相當(dāng)費(fèi)時間的个从,所以這樣的效率就很低了。如果要多次使用同一規(guī)則來進(jìn)行匹配的話歪沃,可以使用 re.compile 函數(shù)來將規(guī)則預(yù)編譯嗦锐,使用編譯過返回的 Regular Expression Object 或叫做 Pattern 對象來進(jìn)行查找。

s='111,222,aaa,bbb,ccc333,444ddd'

rule=r’/b/d+/b’

compiled_rule=re.compile(rule)

compiled_rule.findall(s)

['111', '222']

可見使用 compile 過的規(guī)則使用和未編譯的使用很相似沪曙。 compile 函數(shù)還可以指定一些規(guī)則標(biāo)志奕污,來指定一些特殊選項(xiàng)。多個選項(xiàng)之間用 ’| ’ (位或)連接起來液走。

**I ** **IGNORECASE **忽略大小寫區(qū)別碳默。

**L LOCAL **字符集本地化贾陷。這個功能是為了支持多語言版本的字符集使用環(huán)境的,比如在轉(zhuǎn)義符/w 嘱根,在英文環(huán)境下昵宇,它代表[a-zA-Z0-9] ,即所以英文字符和數(shù)字儿子。如果在一個法語環(huán)境下使用,缺省設(shè)置下砸喻,不能匹配 "é" 或 "?" 柔逼。 加上這 L 選項(xiàng)和就可以匹配了。不過這個對于中文環(huán)境似乎沒有什么用割岛,它仍然不能匹配中文字符愉适。

**M MULTILINE **多行匹配。在這個模式下 ’^’( 代表字符串開頭 ) 和 ’$’( 代表字符串結(jié)尾 ) 將能夠匹配多行的情況癣漆,成為行首和行尾標(biāo)記维咸。比如

s=’123 456/n789 012/n345 678’

rc=re.compile(r’^/d+’) # 匹配一個位于開頭的數(shù)字,沒有使用 M 選項(xiàng)

rc.findall(s)

['123'] # 結(jié)果只能找到位于第一個行首的 ’123’

rcm=re.compile(r’^/d+’,re.M) # 使用 M 選項(xiàng)

rcm.findall(s)

['123', '789', '345'] # 找到了三個行首的數(shù)字

同樣惠爽,對于 ’$’ 來說癌蓖,沒有使用 M 選項(xiàng),它將匹配最后一個行尾的數(shù)字婚肆,即 ’678’ 租副,加上以后,就能匹配三個行尾的數(shù)字 456 012 和 678 了 .

rc=re.compile(r’/d+$’)

rcm=re.compile(r’/d+$’,re.M)

rc.findall(s)

['678']

rcm.findall(s)

['456', '012', '678']

**S DOTALL **‘.’ 號將匹配所有的字符较性。缺省情況下 ’.’ 匹配除換行符 ’/n’ 外的所有字符用僧,使用這一選項(xiàng)以后, ’.’ 就能匹配包括 ’/n’ 的任何字符了赞咙。

**U ** **UNICODE **<tt>/w </tt>, <tt>/W </tt>, <tt>/b </tt>, <tt>/B </tt>, <tt>/d </tt>, <tt>/D </tt>, <tt>/s </tt>和 <tt>/S </tt><tt>都將使用Unicode 责循。</tt>

**X VERBOSE ** 這個選項(xiàng)忽略規(guī)則表達(dá)式中的空白,并允許使用 ’#’ 來引導(dǎo)一個注釋攀操。這樣可以讓你把規(guī)則寫得更美觀些院仿。比如你可以把規(guī)則

<pre>>>> rc
= re.compile(
r
"
/d+|[a-zA-Z]+
")

匹配一個數(shù)字或者單詞

</pre>

使用 X 選項(xiàng)寫成:

<pre>>>> rc
= re.compile(r"""

start a rule

</pre>

<pre>/d+

number

</pre>

<pre>|
[a-zA-Z]+

word

</pre>

<pre>""", re.VERBOSE)

</pre>

<pre>在這個模式下,如果你想匹配一個空格崔赌,你必須用'/ '
的形式('/'
后面跟一個空格)

</pre>

2.2 match ****與 search

match( rule , targetString [,flag] )

search( rule , targetString [,flag] )

(注: re 的 match 與 search 函數(shù)同 compile 過的 Pattern 對象的 match 與 search 函數(shù)的參數(shù)是不一樣的意蛀。 Pattern 對象的 match 與 search 函數(shù)更為強(qiáng)大,是真正最常用的函數(shù))

按照規(guī)則在目標(biāo)字符串中進(jìn)行匹配健芭。

第一個參數(shù)是正則規(guī)則县钥,第二個是目標(biāo)字符串,第三個是選項(xiàng)(同 compile 函數(shù)的選項(xiàng))

返回:若成功返回一個 Match 對象慈迈,失敗無返回

findall 雖然很直觀若贮,但是在進(jìn)行更復(fù)雜的操作時省有,就有些力不從心了。此時更多的使用的是 match 和 search 函數(shù)谴麦。他們的參數(shù)和 findall 是一樣的蠢沿,都是:

match( rule , targetString [,flag] )

search( rule , targetString [,flag] )

不過它們的返回不是一個簡單的字符串列表,而是一個 MatchObject (如果匹配成功的話) . 匾效。通過操作這個 matchObject 舷蟀,我們可以得到更多的信息。

需要注意的是面哼,如果匹配不成功野宜,它們則返回一個 NoneType 。所以在對匹配完的結(jié)果進(jìn)行操作之前魔策,你必需先判斷一下是否匹配成功了匈子,比如:

m=re.match( rule , target )

if m: # 必需先判斷是否成功

    doSomethin

這兩個函數(shù)唯一的區(qū)別是: match 從字符串的開頭開始匹配,如果開頭位置沒有匹配成功闯袒,就算失敗了虎敦;而 search 會跳過開頭,繼續(xù)向后尋找是否有匹配的字符串政敢。針對不同的需要其徙,可以靈活使用這兩個函數(shù)。

關(guān)于 match 返回的 MatchObject 如果使用的問題堕仔,是 Python 正則式的精髓所在擂橘,它與組的使用密切相關(guān)。我將在下一部分詳細(xì)講解摩骨,這里只舉個最簡單的例子:

例:

s= 'Tom:9527 , Sharry:0003'

m=re.match( r'(?P<name>/w+):(?P<num>/d+)' , s )

m.group()

'Tom:9527'

m.groups()

('Tom', '9527')

m.group(‘name’)

'Tom'

m.group(‘num’)

'9527'

2.3 finditer

finditer( rule , target [,flag] )

參數(shù)同 findall

返回一個迭代器

finditer 函數(shù)和 findall 函數(shù)的區(qū)別是通贞, findall 返回所有匹配的字符串,并存為一個列表恼五,而 finditer 則并不直接返回這些字符串昌罩,而是返回一個迭代器。關(guān)于迭代器灾馒,解釋起來有點(diǎn)復(fù)雜茎用,還是看看例子把:

s=’111 222 333 444’

for i in re.finditer(r’/d+’ , s ):

    print i.group(),i.span()          # 打印每次得到的字符串和起始結(jié)束位置

結(jié)果是

111 (0, 3)

222 (4, 7)

333 (8, 11)

444 (12, 15)

簡單的說吧,就是 finditer 返回了一個可調(diào)用的對象睬罗,使用 for i in finditer() 的形式轨功,可以一個一個的得到匹配返回的 Match 對象。這在對每次返回的對象進(jìn)行比較復(fù)雜的操作時比較有用容达。

2.4 ****字符串的替換和修改

re 模塊還提供了對字符串的替換和修改函數(shù)古涧,他們比字符串對象提供的函數(shù)功能要強(qiáng)大一些。這幾個函數(shù)是

sub ( rule , replace , target [,count] )

subn(rule , replace , target [,count] )

在目標(biāo)字符串中規(guī)格規(guī)則查找匹配的字符串花盐,再把它們替換成指定的字符串羡滑。你可以指定一個最多替換次數(shù)菇爪,否則將替換所有的匹配到的字符串。

第一個參數(shù)是正則規(guī)則柒昏,第二個參數(shù)是指定的用來替換的字符串凳宙,第三個參數(shù)是目標(biāo)字符串,第四個參數(shù)是最多替換次數(shù)职祷。

這兩個函數(shù)的唯一區(qū)別是返回值氏涩。

sub 返回一個被替換的字符串

sub 返回一個元組,第一個元素是被替換的字符串有梆,第二個元素是一個數(shù)字削葱,表明產(chǎn)生了多少次替換。

例淳梦,將下面字符串中的 ’dog’ 全部替換成 ’cat’

s=’ I have a dog , you have a dog , he have a dog ‘

re.sub( r’dog’ , ‘cat’ , s )

' I have a cat , you have a cat , he have a cat '

如果我們只想替換前面兩個,則

re.sub( r’dog’ , ‘cat’ , s , 2 )

' I have a cat , you have a cat , he have a dog '

或者我們想知道發(fā)生了多少次替換昔字,則可以使用 subn

re.subn( r’dog’ , ‘cat’ , s )

(' I have a cat , you have a cat , he have a cat ', 3)

split( rule , target [,maxsplit] )

切片函數(shù)爆袍。使用指定的正則規(guī)則在目標(biāo)字符串中查找匹配的字符串,用它們作為分界作郭,把字符串切片陨囊。

第一個參數(shù)是正則規(guī)則,第二個參數(shù)是目標(biāo)字符串夹攒,第三個參數(shù)是最多切片次數(shù)

返回一個被切完的子字符串的列表

這個函數(shù)和 str 對象提供的 split 函數(shù)很相似蜘醋。舉個例子,我們想把上例中的字符串被 ’,’ 分割開咏尝,同時要去掉逗號前后的空格

s=’ I have a dog , you have a dog , he have a dog ‘

re.split( ‘/s,/s’ , s )

[' I have a dog', 'you have a dog', 'he have a dog ']

結(jié)果很好压语。如果使用 str 對象的 split 函數(shù),則由于我們不知道 ’,’ 兩邊會有多少個空格编检,而不得不對結(jié)果再進(jìn)行一次處理胎食。

escape( string )

這是個功能比較古怪的函數(shù),它的作用是將字符串中的 non-alphanumerics 字符(我已不知道該怎么翻譯比較好了)用反義字符的形式顯示出來允懂。有時候你可能希望在正則式中匹配一個字符串厕怜,不過里面含有很多 re 使用的符號,你要一個一個的修改寫法實(shí)在有點(diǎn)麻煩蕾总,你可以使用這個函數(shù) ,

例 在目標(biāo)字符串 s 中匹配 ’(*+?)’ 這個子字符串

s= ‘111 222 (*+?) 333’

rule= re.escape( r’(*+?)’ )

print rule

/(/*/+/?/)

re.findall( rule , s )

['(*+?)']

3 更深入的了解 ****re ****的組與對象

前面對 Python 正則式的組進(jìn)行了一些簡單的介紹粥航,由于還沒有介紹到 match 對象,而組又是和 match 對象密切相關(guān)的生百,所以必須將它們結(jié)合起來介紹才能充分地說明它們的用途递雀。

不過再詳細(xì)介紹它們之前,我覺得有必要先介紹一下將規(guī)則編譯后的生成的 patter 對象

3.1 ****編譯后的 ****Pattern ****對象

將一個正則式置侍,使用 compile 函數(shù)編譯映之,不僅是為了提高匹配的速度拦焚,同時還能使用一些附加的功能。編譯后的結(jié)果生成一個 Pattern 對象杠输,這個對象里面有很多函數(shù)赎败,他們看起來和 re 模塊的函數(shù)非常象,它同樣有 findall , match , search ,finditer , sub , subn , split 這些函數(shù)蠢甲,只不過它們的參數(shù)有些小小的不同僵刮。一般說來, re 模塊函數(shù)的第一個參數(shù)鹦牛,即正則規(guī)則不再需要了搞糕,應(yīng)為規(guī)則就包含在 Pattern 對象中了,編譯選項(xiàng)也不再需要了曼追,因?yàn)橐呀?jīng)被編譯過了窍仰。因此 re 模塊中函數(shù)的這兩個參數(shù)的位置,就被后面的參數(shù)取代了礼殊。

findall , match , search 和 finditer 這幾個函數(shù)的參數(shù)是一樣的驹吮,除了少了規(guī)則和選項(xiàng)兩個參數(shù)外,它們又加入了另外兩個參數(shù)晶伦,它們是:查找開始位置和查找結(jié)束位置碟狞,也就是說,現(xiàn)在你可以指定查找的區(qū)間婚陪,除去你不感興趣的區(qū)間族沃。它們現(xiàn)在的參數(shù)形式是:

findall ( targetString [, startPos [,endPos] ] )

finditer ( targetString [, startPos [,endPos] ] )

match ( targetString [, startPos [,endPos] ] )

search ( targetString [, startPos [,endPos] ] )

這些函數(shù)的使用和 re 模塊的同名函數(shù)使用完全一樣。所以就不多介紹了泌参。

除了和 re 模塊的函數(shù)同樣的函數(shù)外脆淹, Pattern 對象還多了些東西,它們是:

flags ****查詢編譯時的選項(xiàng)

pattern ****查詢編譯時的規(guī)則

groupindex ****規(guī)則里的組

這幾個不是函數(shù)沽一,而是一個值未辆。它們提供你一些規(guī)則的信息。比如下面這個例子

p=re.compile( r'(?P<word>/b[a-z]+/b)|(?P<num>/b/d+/b)|(?P<id>/b[a-z_]+/w*/b)' , re.I )

p.flags

2

p.pattern

'(?P<word>//b[a-z]+//b)|(?P<num>//b//d+//b)|(?P<id>//b[a-z_]+//w*//b)'

p.groupindex

{'num': 2, 'word': 1, 'id': 3}

我們來分析一下這個例子:這個正則式是匹配單詞锯玛、或數(shù)字咐柜、或一個由字母或 ’_’ 開頭,后面接字母或數(shù)字的一個 ID 攘残。我們給這三種情況的規(guī)則都包入了一個命名組拙友,分別命名為 ’word’ , ‘num’ 和 ‘id’ 。我們規(guī)定大小寫不敏感歼郭,所以使用了編譯選項(xiàng) ‘I’ 遗契。

編譯以后返回的對象為 p ,通過 p.flag 我們可以查看編譯時的選項(xiàng)病曾,不過它顯示的不是 ’I’ 牍蜂,而是一個數(shù)值 2 漾根。其實(shí) re.I 是一個整數(shù), 2 就是它的值鲫竞。我們可以查看一下:

re.I

2

re.L

4

re.M

8

每個選項(xiàng)都是一個數(shù)值辐怕。

通過 p.pattern 可以查看被編譯的規(guī)則是什么。使用 print 的話會更好看一些

print p.pattern

(?P<word>/b[a-z]+/b)|(?P<num>/b/d+/b)|(?P<id>/b[a-z_]+/w*/b)

看从绘,和我們輸入的一樣寄疏。

接下來的 p.groupindex 則是一個字典,它包含了規(guī)則中的所有命名組僵井。字典的 key 是名字陕截, values 是組的序號。由于字典是以名字作為 key 批什,所以一個無命名的組不會出現(xiàn)在這里农曲。

3.2 ****組與 Match ****對象

組與 Match 對象是 Python 正則式的重點(diǎn)。只有掌握了組和 Match 對象的使用驻债,才算是真正學(xué)會了 Python 正則式朋蔫。

3.2.1 ****組的名字與序號

正則式中的每個組都有一個序號,它是按定義時從左到右的順序從 1 開始編號的却汉。其實(shí), re 的正則式還有一個 0 號組荷并,它就是整個正則式本身合砂。

我們來看個例子

p=re.compile( r’(?P<name>[a-z]+)/s+(?P<age>/d+)/s+(?P<tel>/d+).*’ , re.I )

p.groupindex

{'age': 2, 'tel': 3, 'name': 1}

s=’Tom 24 88888888 <=’

m=p.search(s)

m.groups() # 看看匹配的各組的情況

('Tom', '24', '8888888')

m.group(‘name’) # 使用組名獲取匹配的字符串

‘Tom’

m.group( 1 ) # 使用組序號獲取匹配的字符串,同使用組名的效果一樣

m.group(0) # 0 組里面是什么呢源织?

'Tom 24 88888888 <='

原來 0 組就是整個正則式 , 包括沒有被包圍到組里面的內(nèi)容翩伪。當(dāng)獲取 0 組的時候,你可以不寫這個參數(shù)谈息。 m.group(0) 和 m.group() 的效果是一樣的:

m.group()

'Tom 24 88888888 <='

接下來看看更多的 Match 對象的方法缘屹,看看我們能做些什么。

3.2.2 ****Match ****對象的方法

**group([index|id]) **獲取匹配的組侠仇,缺省返回組 0, 也就是全部值

**groups() ** 返回全部的組

**groupdict() ** 返回以組名為 key 轻姿,匹配的內(nèi)容為 values 的字典

接上例:

m.groupindex()

{'age': '24', 'tel': '88888888', 'name': 'Tom'}

**start( [group] ) **獲取匹配的組的開始位置

**end( [group] ) **獲取匹配的組的結(jié)束位置

**span( [group] ) **獲取匹配的組的(開始,結(jié)束)位置

**expand( template ) **根據(jù)一個模版用找到的內(nèi)容替換模版里的相應(yīng)位置

這個功能比較有趣逻炊,它根據(jù)一個模版來用匹配到的內(nèi)容替換模版中的相應(yīng)位置互亮,組成一個新的字符串返回。它使用 /g<index|name> 或 /index 來指示一個組余素。

接上例

m.expand(r'name is /g<1> , age is /g<age> , tel is /3')

'name is Tom , age is 24 , tel is 88888888'

除了以上這些函數(shù)外豹休, Match 對象還有些屬性

**pos ** 搜索開始的位置參數(shù)

**endpos ** 搜索結(jié)束的位置參數(shù)

這兩個是使用 findall 或 match 等函數(shù)時,傳入的參數(shù)桨吊。在上面這個例子里威根,我們沒有指定開始和結(jié)束位置凤巨,那么缺省的開始位置就是 0, 結(jié)束位置就是最后。

m.pos

0

m.endpos

19

<tt>**lastindex **</tt><tt>最后匹配的組的序號</tt>

<tt>>>> m.lastindex</tt>

<tt>3</tt>

**lastgroup **最后匹配的組名

m.lastgroup

'tel'

**re ** 產(chǎn)生這個匹配的 Pattern 對象洛搀,可以認(rèn)為是個逆引用

m.re.pattern

'(?P<name>[a-z]+)//s+(?P<age>//d+)//s+(?P<tel>//d+).*'

得到了產(chǎn)生這個匹配的規(guī)則

<tt>**string **</tt><tt>匹配的目標(biāo)字符串</tt>

<tt>>>> m.string</tt>

'Tom 24 88888888 <='

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末敢茁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子姥卢,更是在濱河造成了極大的恐慌卷要,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件独榴,死亡現(xiàn)場離奇詭異僧叉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)棺榔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門瓶堕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人症歇,你說我怎么就攤上這事郎笆。” “怎么了忘晤?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵宛蚓,是天一觀的道長。 經(jīng)常有香客問我设塔,道長凄吏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任闰蛔,我火速辦了婚禮痕钢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘序六。我一直安慰自己任连,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布例诀。 她就那樣靜靜地躺著随抠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪繁涂。 梳的紋絲不亂的頭發(fā)上暮刃,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機(jī)與錄音爆土,去河邊找鬼椭懊。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的氧猬。 我是一名探鬼主播背犯,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼盅抚!你這毒婦竟也來了漠魏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤妄均,失蹤者是張志新(化名)和其女友劉穎柱锹,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丰包,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡禁熏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了邑彪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞧毙。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖寄症,靈堂內(nèi)的尸體忽然破棺而出宙彪,到底是詐尸還是另有隱情,我是刑警寧澤有巧,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布释漆,位于F島的核電站,受9級特大地震影響篮迎,放射性物質(zhì)發(fā)生泄漏男图。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一柑潦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧峻凫,春花似錦渗鬼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至命锄,卻和暖如春堰乔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背脐恩。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工镐侯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人驶冒。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓苟翻,卻偏偏與公主長得像韵卤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子崇猫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

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