正表達式就是一段匹配文本片段的模式,在Python 中 re
模塊包含了對正則表達式(regular expression)的支持。
1. 正則表達式的基本概念
1. 通配符
點號( .
)可以匹配換行符之外的任何單個字符,被稱之為通配符。
2. 特殊字符轉義
將有特殊含義的字符作為普通字符使用時需要進行轉義。例如想要匹配 python.org
時需要將表達式寫為: python\\.org
才行。
為什么使用兩個反斜線?
這是為了通過解釋器進行轉義,需要進行兩個級別的轉義:1.通過解釋器的轉義;2.通過 re 模塊轉義。如果不想使用兩個反斜線,可以考慮使用原始字符串,如:
r'python\.org'
。
3. 字符集
字符集是在中括號( []
)中包含字符串。字符集可以匹配它所包含的任意字符。即'[pj]ython'
可以匹配 python
和 jython
。
使用范圍
可以使用范圍,如
'[a-z]'
可以匹配 a 到 z 的任意一個字符。'a-zA-Z0-9'
可以匹配任意大小寫的一個字母或數字。
反轉字符集
我們也可以對字符集進行反轉,比如
'[^abc]'
匹配除了a、b和c之外的任何字符。
字符集中的特殊字符
特殊字符在模式中做文本字符,而不是正則表達式運算符的話需要對其進行轉義。但是在字符集中並不需要,只有以三種情況下,需要將特殊字符作為普通文本使用時,需要對字符進行轉義:
^
脫字符作為字符集的開頭]
右中括號作為字符集的開頭-
橫線(字符范圍)作為字符集的開頭
4. 選擇符合子模式
管道符號( |
)是用於選擇項的特殊字符。例如: 'python|ruby'
匹配python和ruby這兩個單詞。
子模式(subparttern)是指:使用圓括號將選擇項括起來。例如 'p(ython|erl)'
匹配python和perl。
5. 可選項和重復子模式
在子模式后面加上一個問號,它就變成了一個可選項,例如:
r'(http://)?(www\.)?python\.org$'
上面的模式只能匹配下面的字符串:
'http://www.python.org' 'http://python.org' 'www.python.org' 'python.org'
問號表示子模式可以出現一次或者根本不出現,下面的運算符允許子模式重復多次:
- (pattern)*: 允許模式重復0次或多次
- (pattern)+: 允許模式出現一次或多次
- (pattern){m-n}: 允許模式重復m~n次
6. 字符串的開始和結尾
使用 ^
脫字符標記字符串開始;使用美元符號 $
標識字符串的結尾。如:
'^Python$'
2. re 模塊
re 模塊包含了很多操作正則表達式的函數,以下是其中最常用的函數:
1 compile(pattern[, flags]) 根據包含正則表達式的字符串創建模式對象 2 search(pattern, string[, flags]) 在字符串中尋找模式 3 match(pattern, string[, flags]) 在字符串的開始處匹配模式 4 split(pattern, string[, maxsplit=0]) 根據模式的匹配項來分割字符串 5 findall(pattern, string) 列出字符串中模式的所有匹配項 6 sub(pat, repl, string[, count=0]) 將字符串中所有pat的匹配項用repl替換 7 escape(string) 將字符串中所有特殊正則表達式字符轉義
下面是這些函數的的簡單示例:
1 # --coding: utf-8 -- 2 import re 3 4 # search 5 pattern = r'(http://)?(www\.)?python\.org$' 6 string = 'python.org' 7 if re.search(pattern,string): 8 print 'found it' 9 10 # match 11 text = 'alpha,beta,,,,,,gamma delta' 12 pattern = '[,]+' # 注意+號 13 print re.split(pattern,text) # ['alpha', 'beta', 'gamma delta'] 14 15 # findall 16 pattern = '[a-zA-Z]+' # 匹配單詞 17 text = '"Hm... Err -- are you sure?" he said, sounding insecure.' 18 # ['Hm', 'Err', 'are', 'you', 'sure', 'he', 'said', 'sounding', 'insecure'] 19 print re.findall(pattern,text) 20 21 pattern = r'[.?\-",]' # 匹配標點符號 22 # ['"', '.', '.', '.', '-', '-', '?', '"', ',', '.'] 23 print re.findall(pattern,text) 24 25 # sub 26 pattern = '{name}' 27 text = 'Dear {name}...' 28 print re.sub(pattern, 'Mr. Gumby', text) # Dear Mr. Gumby... 29 30 # escape 31 print re.escape('www.python.org') # www\.python\.org 32 print re.escape('But where is the ambiguity?') # But\ where\ is\ the\ ambiguity\?
2.1 匹配對象和組
當 re
模塊中對字符串進行匹配的函數找到匹配項時,就會返回一個 MatchObject
對象。
組的概念
該對象包含了匹配模式的子字符串的信息,這些信息由組(group)構成。簡而言之,組就是放置在圓括號內的子模式。組的序號取決於它左側的括號數。組0就是整個模式。在下面的模式中:
'There (was a (wee) (cooper)) who (lived in Fyfe)'
包含這些組:
0 There was a wee cooper who lived in Fyfe 1 was a wee cooper 2 wee 3 cooper 4 lived in Fyfe
下面是 re 匹配對象的常用方法:
1 group([group1], ...]) 獲取給定子模式(組)的匹配項 2 start([start]) 返回給定組匹配項的開始位置(返回結果是索引從0開始) 3 end([end]) 返回給定組匹配項的結束位置(返回結果是索引加1,和分片一樣,不包括組的結束位置) 4 span([group]) 返回一個組的開始和結束位置
示例如下:
1 import re 2 3 m = re.match(r'www\.(.*)\..{3}','www.python.org') 4 print m.group(1) # python 5 print m.start(1) # 4 6 print m.end(1) # 10 7 print m.span(1) # (4, 10)
除了整體匹配以為(組0),只能使用99個組,即組的范圍在1-99之間
2.2 使用re的替換函數
通過使用 re.sub
函數和組號的結合,還可以實現更加復雜的字符串提供功能,如下所示:
import re emphasis_pattern = r'\*([^\*]+)\*' # hello, <em>world</em>! print re.sub(emphasis_pattern,r'<em>\1</em>','hello, *world*!')
貪婪模式和非貪婪模式
重復運算符默認是貪婪的( greedy
),它會進行盡可能多的匹配。如下面的模式使用的就是貪婪模式:
1 import re 2 3 emphasis_pattern = r'\*(.+)\*' 4 text = '*This* is *it*' 5 # <em>This* is *it<em> 6 print re.sub(emphasis_pattern,r'<em>\1<em>',text)
非貪婪模式和貪婪模式相反,它會盡可能少的匹配。將重復運算符變成非貪婪模式只需要在其后加一個問號( ?
)即可:
1 import re 2 3 emphasis_pattern = r'\*(.+?)\*' 4 text = '*This* is *it*' 5 # <em>This<em> is <em>it<em> 6 print re.sub(emphasis_pattern,r'<em>\1<em>',text)