本模塊提供了和Perl里的正則表達式類似的功能,不關是正則表達式本身還是被搜索的字符串,都可以是Unicode字符,這點不用擔心,python會處理地和Ascii字符一樣漂亮。
正則表達式使用反斜桿(/)來轉義特殊字符,使其可以匹配字符本身,而不是指定其他特殊的含義。這可能會和python字面意義上的字符串轉義相沖突,這也許有些令人費解。比如,要匹配一個反斜桿本身,你也許要用'////'來做為正則表達式的字符串,因為正則表達式要是//,而字符串里,每個反斜桿都要寫成//。
你也可以在字符串前加上 r 這個前綴來避免部分疑惑,因為 r 開頭的python字符串是 raw 字符串,所以里面的所有字符都不會被轉義,比如r'/n'這個字符串就是一個反斜桿加上一字母n,而'/n'我們知道這是個換行符。因此,上面的'////'你也可以寫成r'//',這樣,應該就好理解很多了。可以看下面這段:
正則表達式語法
正則表達式(RE)指定一個與之匹配的字符集合;本模塊所提供的函數,將可以用來檢查所給的字符串是否與指定的正則表達式匹配。
正則表達式可以被連接,從而形成新的正則表達式;例如A和B都是正則表達式,那么AB也是正則表達式。一般地,如果字符串p與A匹配,q與B匹配的話,那么字符串pq也會與AB匹配,但A或者B里含有邊界限定條件或者命名組操作的情況除外。也就是說,復雜的正則表達式可以用簡單的連接而成。
正則表達式可以包含特殊字符和普通字符,大部分字符比如'A','a'和'0'都是普通字符,如果做為正則表達式,它們將匹配它們本身。由于正則表達式可以連接,所以連接多個普通字符而成的正則表達式last也將匹配'last'。(后面將用不帶引號的表示正則表達式,帶引號的表示字符串)
下面就來介紹正則表達式的特殊字符:
'.'
點號,在普通模式,它匹配除換行符外的任意一個字符;如果指定了 DOTALL 標記,匹配包括換行符以內的任意一個字符。
'^'
尖尖號,匹配一個字符串的開始,在 MULTILINE 模式下,也將匹配任意一個新行的開始。
'$'
美元符號,匹配一個字符串的結尾或者字符串最后面的換行符,在 MULTILINE 模式下,也匹配任意一行的行尾。也就是說,普通模式下,foo.$去搜索'foo1/nfoo2/n'只會找到'foo2′,但是在 MULTILINE 模式,還能找到 ‘foo1′,而且就用一個 $ 去搜索'foo/n'的話,會找到兩個空的匹配:一個是最后的換行符,一個是字符串的結尾,演示:
'*'
星號,指定將前面的RE重復0次或者任意多次,而且總是試圖盡量多次地匹配。
'+'
加號,指定將前面的RE重復1次或者任意多次,而且總是試圖盡量多次地匹配。
'?'
問號,指定將前面的RE重復0次或者1次,如果有的話,也盡量匹配1次。
*?, +?, ??
從前面的描述可以看到'*','+'和'?'都是貪婪的,但這也許并不是我們說要的,所以,可以在后面加個問號,將策略改為非貪婪,只匹配盡量少的RE。示例,體會兩者的區別:
{m,n}
m和n都是數字,指定將前面的RE重復m到n次,例如a{3,5}匹配3到5個連續的a。注意,如果省略m,將匹配0到n個前面的RE;如果省略n,將匹配n到無窮多個前面的RE;當然中間的逗號是不能省略的,不然就變成前面那種形式了。
{m,n}?
前面說的{m,n},也是貪婪的,a{3,5}如果有5個以上連續a的話,會匹配5個,這個也可以通過加問號改變。a{3,5}?如果可能的話,將只匹配3個a。
'/'
反斜桿,轉義'*','?'等特殊字符,或者指定一個特殊序列(下面會詳述)
由于之前所述的原因,強烈建議用raw字符串來表述正則。
[]
方括號,用于指定一個字符的集合。可以單獨列出字符,也可以用'-'連接起止字符以表示一個范圍。特殊字符在中括號里將失效,比如[akm$]就表示字符'a','k','m',或'$',在這里$也變身為普通字符了。[a-z]匹配任意一個小寫字母,[a-zA-Z0-9]匹配任意一個字母或數字。如果你要匹配']'或'-'本身,你需要加反斜桿轉義,或者是將其置于中括號的最前面,比如[]]可以匹配']'
你還可以對一個字符集合取反,以匹配任意不在這個字符集合里的字符,取反操作用一個'^'放在集合的最前面表示,放在其他地方的'^'將不會起特殊作用。例如[^5]將匹配任意不是'5'的字符;[^^]將匹配任意不是'^'的字符。
注意:在中括號里,+、*、(、)這類字符將會失去特殊含義,僅作為普通字符。反向引用也不能在中括號內使用。
'|'
管道符號,A和B是任意的RE,那么A|B就是匹配A或者B的一個新的RE。任意個數的RE都可以像這樣用管道符號間隔連接起來。這種形式可以被用于組中(后面將詳述)。對于目標字符串,被'|'分割的RE將自左至右一一被測試,一旦有一個測試成功,后面的將不再被測試,即使后面的RE可能可以匹配更長的串,換句話說,'|'操作符是非貪婪的。要匹配字面意義上的'|',可以用反斜桿轉義:/|,或是包含在反括號內:[|]。
(...)
匹配圓括號里的RE匹配的內容,并指定組的開始和結束位置。組里面的內容可以被提取,也可以采用/number這樣的特殊序列,被用于后續的匹配。要匹配字面意義上的'('和')',可以用反斜桿轉義:/(、/),或是包含在反括號內:[(]、[)]。
(?...)
這是一個表達式的擴展符號。'?'后的第一個字母決定了整個表達式的語法和含義,除了(?P...)以外,表達式不會產生一個新的組。下面介紹幾個目前已被支持的擴展:
(?iLmsux)
'i'、'L'、'm'、's'、'u'、'x'里的一個或多個字母。表達式不匹配任何字符,但是指定相應的標志:re.I(忽略大小寫)、re.L(依賴locale)、re.M(多行模式)、re.S(.匹配所有字符)、re.U(依賴Unicode)、re.X(詳細模式)。關于各個模式的區別,下面會有專門的一節來介紹的。使用這個語法可以代替在re.compile()的時候或者調用的時候指定flag參數。
例如,上面舉過的例子,可以改寫成這樣(和指定了re.MULTILINE是一樣的效果):
(?:...)
匹配內部的RE所匹配的內容,但是不建立組。
(?P<name>...)
和普通的圓括號類似,但是子串匹配到的內容將可以用命名的name參數來提取。組的name必須是有效的python標識符,而且在本表達式內不重名。命名了的組和普通組一樣,也用數字來提取,也就是說名字只是個額外的屬性。
演示一下:
(?#...)
注釋,圓括號里的內容會被忽略。
(?=...)
如果 ... 匹配接下來的字符,才算匹配,但是并不會消耗任何被匹配的字符。例如 Isaac (?=Asimov) 只會匹配后面跟著 'Asimov' 的 'Isaac ',這個叫做“前瞻斷言”。
(?!...)
和上面的相反,只匹配接下來的字符串不匹配 ... 的串,這叫做“反前瞻斷言”。
(?<=...)
只有當當前位置之前的字符串匹配 ... ,整個匹配才有效,這叫“后顧斷言”。字符串'abcdef'可以匹配正則(?<=abc)def,因為會后向查找3個字符,看是否為abc。所以內置的子RE,需要是固定長度的,比如可以是abc、a|b,但不能是a*、a{3,4}。注意這種RE永遠不會匹配到字符串的開頭。舉個例子,找到連字符('-')后的單詞:
(?(id/name)yes-pattern|no-pattern)
如有由id或者name指定的組存在的話,將會匹配yes-pattern,否則將會匹配no-pattern,通常情況下no-pattern也可以省略。例如:(<)?(/w+@/w+(?:/./w+)+)(?(1)>)可以匹配 '<user@host.com>' 和 'user@host.com',但是不會匹配 '<user@host.com'。
下面列出以'/'開頭的特殊序列。如果某個字符沒有在下面列出,那么RE的結果會只匹配那個字母本身,比如,/$只匹配字面意義上的'$'。
/number
匹配number所指的組相同的字符串。組的序號從1開始。例如:(.+) /1可以匹配'the the'和'55 55',但不匹配'the end'。這種序列在一個正則表達式里最多可以有99個,如果number以0開頭,或是有3位以上的數字,就會被當做八進制表示的字符了。同時,這個也不能用于方括號內。
/A
只匹配字符串的開始。
/b
匹配單詞邊界(包括開始和結束),這里的“單詞”,是指連續的字母、數字和下劃線組成的字符串。注意,/b的定義是/w和/W的交界,所以精確的定義有賴于UNICODE和LOCALE這兩個標志位。
/B
和/b相反,/B匹配非單詞邊界。也依賴于UNICODE和LOCALE這兩個標志位。
/d
未指定UNICODE標志時,匹配數字,等效于:[0-9]。指定了UNICODE標志時,還會匹配其他Unicode庫里描述為字符串的符號。便于理解,舉個例子(好不容易找的例子啊,呵呵):
/D
和/d相反,不多說了。
/s
當未指定UNICODE和LOCALE這兩個標志位時,匹配任何空白字符,等效于[ /t/n/r/f/v]。如果指定了LOCALE,則還要加LOCALE相關的空白字符;如果指定了UNICODE,還要加上UNICODE空白字符,如較常見的空寬度連接空格(/uFEFF)、零寬度非連接空格(/u200B)等。
/S
和/s相反,也不多說。
/w
當未指定UNICODE和LOCALE這兩個標志位時,等效于[a-zA-Z0-9_]。當指定了LOCALE時,為[0-9_]加上當前LOCAL指定的字母。當指定了UNICODE時,為[0-9_]加上UNICODE庫里的所有字母。
/W
和/w相反,不多說。
/Z
只匹配字符串的結尾。
匹配之搜索
python提供了兩種基于正則表達式的操作:匹配(match)從字符串的開始檢查字符串是否個正則匹配。而搜索(search)檢查字符串任意位置是否有匹配的子串(perl默認就是如此)。
注意,即使search的正則以'^'開頭,match和search也還是有許多不同的。
模塊的屬性和方法
re.compile(pattern[, flags])
把一個正則表達式pattern編譯成正則對象,以便可以用正則對象的match和search方法。
得到的正則對象的行為(也就是模式)可以用flags來指定,值可以由幾個下面的值OR得到。
以下兩段內容在語法上是等效的:
區別是,用了re.compile以后,正則對象會得到保留,這樣在需要多次運用這個正則對象的時候,效率會有較大的提升。再用上面用過的例子來演示一下,用相同的正則匹配相同的字符串,執行100萬次,就體現出compile的效率了(數據來自我那1.86G CPU的神舟本本):
re.L
re.LOCALE
讓/w、/W、/b、/B、/s和/S依賴當前的locale。
re.M
re.MULTILINE
影響'^'和'$'的行為,指定了以后,'^'會增加匹配每行的開始(也就是換行符后的位置);'$'會增加匹配每行的結束(也就是換行符前的位置)。
re.S
re.DOTALL
影響'.'的行為,平時'.'匹配除換行符以外的所有字符,指定了本標志以后,也可以匹配換行符。
re.U
re.UNICODE
讓/w、/W、/b、/B、/d、/D、/s和/S依賴Unicode庫。
re.X
re.VERBOSE
運用這個標志,你可以寫出可讀性更好的正則表達式:除了在方括號內的和被反斜杠轉義的以外的所有空白字符,都將被忽略,而且每行中,一個正常的井號后的所有字符也被忽略,這樣就可以方便地在正則表達式內部寫注釋了。也就是說,下面兩個正則表達式是等效的:
re.match(pattern, string[, flags])
如果字符串string的開頭和正則表達式pattern匹配的話,返回一個相應的MatchObject的實例,否則返回None
注意:要在字符串的任意位置搜索的話,需要使用上面的search()。
re.split(pattern, string[, maxsplit=0])
用匹配pattern的子串來分割string,如果pattern里使用了圓括號,那么被pattern匹配到的串也將作為返回值列表的一部分。如果maxsplit不為0,則最多被分割為maxsplit個子串,剩余部分將整個地被返回。
re.sub(pattern, repl, string[, count])
替換,將string里,匹配pattern的部分,用repl替換掉,最多替換count次(剩余的匹配將不做處理),然后返回替換后的字符串。如果string里沒有可以匹配pattern的串,將被原封不動地返回。repl可以是一個字符串,也可以是一個函數(也可以參考我以前的例子)。如果repl是個字符串,則其中的反斜桿會被處理過,比如 /n 會被轉成換行符,反斜桿加數字會被替換成相應的組,比如 /6 表示pattern匹配到的第6個組的內容。
例子:
re.subn(pattern, repl, string[, count])
跟上面的sub()函數一樣,只是它返回的是一個元組 (新字符串, 匹配到的次數)
,還是用例子說話:
exception re.error
如果字符串不能被成功編譯成正則表達式或者正則表達式在匹配過程中出錯了,都會拋出此異常。但是如果正則表達式沒有匹配到任何文本,是不會拋出這個異常的。
正則對象
正則對象由re.compile()返回。它有如下的屬性和方法。
match(string[, pos[, endpos]])
作用和模塊的match()函數類似,區別就是后面兩個參數。
pos是開始搜索的位置,默認為0。endpos是搜索的結束位置,如果endpos比pos還小的話,結果肯定是空的。也就是說只有pos 到 endpos-1 位置的字符串將會被搜索。
例子:
split(string[, maxsplit=0])
findall(string[, pos[, endpos]])
finditer(string[, pos[, endpos]])
sub(repl, string[, count=0])
subn(repl, string[, count=0])
這幾個函數,都和模塊的相應函數一致。
flags
編譯本RE時,指定的標志位,如果未指定任何標志位,則為0。
groups
RE所含有的組的個數。
groupindex
一個字典,定義了命名組的名字和序號之間的關系。
例子:這個正則有3個組,如果匹配到,第一個叫區號,最后一個叫分機號,中間的那個未命名
pattern
建立本RE的原始字符串,相當于源代碼了,呵呵。
還是上面這個正則,可以看到,會原樣返回:
Match對象
re.MatchObject被用于布爾判斷的時候,始終返回True,所以你用 if 語句來判斷某個 match() 是否成功是安全的。
它有以下方法和屬性:
expand(template)
用template做為模板,將MatchObject展開,就像sub()里的行為一樣,看例子:
如果有其中有用(?P...)這種語法命名過的子串的話,相應的groupN也可以是名字字符串。例如:
如果某個組被匹配到多次,那么只有最后一次的數據,可以被提取到:
default的作用:
groupdict([default])
返回一個包含所有命名組的名字和子串的字典,default參數,用于給那些沒有匹配到的組做默認值,它的默認值是None,例如:
返回的是:被組group匹配到的子串在原字符串中的位置。如果不指定group或group指定為0,則代表整個匹配。如果group未匹配到,則返回 -1。
對于指定的m和g,m.group(g)和m.string[m.start(g):m.end(g)]等效。
注意:如果group匹配到空字符串,m.start(group)和m.end(group)將相等。
例如:
span([group])
返回一個元組: (m.start(group), m.end(group))
pos
就是傳給RE對象的search()或match()方法的參數pos,代表RE開始搜索字符串的位置。
endpos
就是傳給RE對象的search()或match()方法的參數endpos,代表RE搜索字符串的結束位置。
lastindex
最后一次匹配到的組的數字序號,如果沒有匹配到,將得到None。
例如:(a)b、((a)(b))和((ab))正則去匹配'ab'的話,得到的lastindex為1。而用(a)(b)去匹配'ab'的話,得到的lastindex為2。
lastgroup
最后一次匹配到的組的名字,如果沒有匹配到或者最后的組沒有名字,將得到None。
re
得到本Match對象的正則表達式對象,也就是執行search()或match()的對象。
string
傳給search()或match()的字符串。
后面的例子就略了吧,文中已經加了很多我自己的例子了,需要更多例子的話,參照英文原文吧(https://docs.python.org/2/library/re.html)。
PS:關于正則表達式,這里再為大家提供2款非常方便的正則表達式工具供大家參考使用:
JavaScript正則表達式在線測試工具:
http://tools.VeVB.COm/regex/javascript
正則表達式在線生成工具:
http://tools.VeVB.COm/regex/create_reg
新聞熱點
疑難解答
圖片精選