正則表達式是一個特殊的字元序列,它能幫助你方便的檢查一個字元串是否與某種模式匹配。 一、元字元 1) . --匹配任意字元(不包括換行符) 2) ^ --匹配開始位置,多行模式下匹配每一行的開始 3) $ --匹配結束位置,多行模式下匹配每一行的結束 4) * --匹配前一個元字元0到多次 5) + ...
正則表達式是一個特殊的字元序列,它能幫助你方便的檢查一個字元串是否與某種模式匹配。
一、元字元
1) . --匹配任意字元(不包括換行符)
2) ^ --匹配開始位置,多行模式下匹配每一行的開始
3) $ --匹配結束位置,多行模式下匹配每一行的結束
4) * --匹配前一個元字元0到多次
5) + --匹配前一個元字元1到多次
6) ? --匹配前一個元字元0到1次
7) {m,n} --匹配前一個元字元m到n次
8) \\ --轉義字元,跟在其後的字元將失去作為特殊元字元的含義,例如\\.只能匹配.,不能再匹配任意字元
9) [] --字元集,一個字元的集合,可匹配其中任意一個字元
10) | --邏輯表達式 或 ,比如 a|b 代表可匹配 a 或者 b
11) (...) -- 分組,預設為捕獲,即被分組的內容可以被單獨取出,預設每個分組有個索引,從 1 開始,按照"("的順序決定索引值
12) (?iLmsux) -- 分組中可以設置模式,iLmsux之中的每個字元代表一個模式,用法參見 模式 I
13) (?:...) -- 分組的不捕獲模式,計算索引時會跳過這個分組
14) (?P<name>...) -- 分組的命名模式,取此分組中的內容時可以使用索引也可以使用name
15) (?P=name) -- 分組的引用模式,可在同一個正則表達式用引用前面命名過的正則
16) (?#...) -- 註釋,不影響正則表達式其它部分,用法參見 模式 I
17) (?=...) -- 順序肯定環視,表示所在位置右側能夠匹配括弧內正則
18 (?!...) -- 順序否定環視,表示所在位置右側不能匹配括弧內正則
19) (?<=...) -- 逆序肯定環視,表示所在位置左側能夠匹配括弧內正則
20) (?<!...) --逆序否定環視,表示所在位置左側不能匹配括弧內正則
21) (?(id/name)yes|no) -- 若前面指定id或name的分區匹配成功則執行yes處的正則,否則執行no處的正則
22) \number -- 匹配和前面索引為number的分組捕獲到的內容一樣的字元串
23) \A -- 匹配字元串開始位置,忽略多行模式
24) \Z -- 匹配字元串結束位置,忽略多行模式
25) \b -- 匹配位於單詞開始或結束位置的空字元串
26) \B -- 匹配不位於單詞開始或結束位置的空字元串
27) \d -- 匹配一個數字, 相當於 [0-9]
28) \D -- 匹配非數字,相當於 [^0-9]
29) \s -- 匹配任意空白字元, 相當於 [ \t\n\r\f\v]
30) \S -- 匹配非空白字元,相當於 [^ \t\n\r\f\v]
31) \w -- 匹配數字、字母、下劃線中任意一個字元, 相當於 [a-zA-Z0-9_]
32) \W -- 匹配非數字、字母、下劃線中的任意字元,相當於 [^a-zA-Z0-9_]
二、函數 (參見 python 模塊 re 文檔)
2.1 compile(pattern, flags=0)
給定一個正則表達式 pattern,指定使用的模式 flags 預設為0 即不使用任何模式,然後會返回一個 SRE_Pattern
示例:
regex = re.compile(".+")
print regex
# >>> <_sre.SRE_Pattern object at 0x00000000026BB0B8>
這個對象可以調用其他函數來完成匹配,一般來說推薦使用 compile 函數預編譯出一個正則模式之後再去使用,這樣在後面的代碼中可以很方便的復用它,當然大部分函數也可以不用 compile 直接使用,具體見 findall 函數
示例:
s = '''first line
second line
third line'''
# 調用 findall 函數
print regex.findall(s)
#>>> ['first line', 'second line', 'third line']
# 調用 search 函數
print regex.search(s).group()
# >>> first lin
2.2 escape(pattern)
轉義 如果你需要操作的文本中含有正則的元字元,你在寫正則的時候需要將元字元加上反斜扛 \ 去匹配自身, 而當這樣的字元很多時,寫出來的正則表達式就看起來很亂而且寫起來也挺麻煩的,這個時候你可以使用這個函數,用法如下
示例:
s = ".+\d123"
regex_str = re.escape(".+\d123")
# 查看轉義後的字元
print regex_str
# >>> \.\+\\d123
# 查看匹配到的結果
for g in re.findall(regex_str, s):
print g
# >>> .+\d123
2.3 findall(pattern, string, flags=0)
參數 pattern 為正則表達式, string 為待操作字元串, flags 為所用模式,函數作用為在待操作字元串中尋找所有匹配正則表達式的字串,返回一個列表,如果沒有匹配到任何子串,返回一個空列表。
示例:
s = '''first line
second line
third line'''
# compile 預編譯後使用 findall
regex = re.compile("\w+")
print regex.findall(s)
# >>> ['first', 'line', 'second', 'line', 'third', 'line']
# 不使用 compile 直接使用 findall
print re.findall("\w+", s)
# >>> ['first', 'line', 'second', 'line', 'third', 'line']
2.4 finditer(pattern, string, flags=0)
參數和作用與 findall 一樣,不同之處在於 findall 返回一個列表, finditer 返回一個迭代器, 而且迭代器每次返回的值並不是字元串,而是一個 SRE_Match (參見 第四小節 re 內置對象用法) 對象,這個對象的具體用法見 match 函數。
示例:
s = '''first line
second line
third line'''
regex = re.compile("\w+")
print regex.finditer(s)
# >>> <callable-iterator object at 0x0000000001DF3B38>
for i in regex.finditer(s):
print i
# >>> <_sre.SRE_Match object at 0x0000000002B7A920>
# <_sre.SRE_Match object at 0x0000000002B7A8B8>
# <_sre.SRE_Match object at 0x0000000002B7A920>
# <_sre.SRE_Match object at 0x0000000002B7A8B8>
# <_sre.SRE_Match object at 0x0000000002B7A920>
# <_sre.SRE_Match object at 0x0000000002B7A8B8>
2.5 match(pattern, string, flags=0)
使用指定正則去待操作字元串中尋找可以匹配的子串, 返回匹配上的第一個字串,並且不再繼續找,需要註意的是 match 函數是從字元串開始處開始查找的,如果開始處不匹配,則不再繼續尋找,返回值為 一個 SRE_Match 對象,找不到時返回 None
示例:
s = '''first line
second line
third line'''
# compile
regex = re.compile("\w+")
m = regex.match(s)
print m
# >>> <_sre.SRE_Match object at 0x0000000002BCA8B8>
print m.group()
# >>> first
# s 的開頭是 "f", 但正則中限制了開始為 i 所以找不到
regex = re.compile("^i\w+")
print regex.match(s)
# >>> None
2.6 purge()
當你在程式中使用 re 模塊,無論是先使用 compile 還是直接使用比如 findall 來使用正則表達式操作文本,re 模塊都會將正則表達式先編譯一下, 並且會將編譯過後的正則表達式放到緩存中,這樣下次使用同樣的正則表達式的時候就不需要再次編譯, 因為編譯其實是很費時的,這樣可以提升效率,而預設緩存的正則表達式的個數是 100, 當你需要頻繁使用少量正則表達式的時候,緩存可以提升效率,而使用的正則表達式過多時,緩存帶來的優勢就不明顯了, 這個函數的作用是清除緩存中的正則表達式,可能在你需要優化占用記憶體的時候會用到。
2.7 search(pattern, string, flags=0)
函數類似於 match,不同之處在於不限制正則表達式的開始匹配位置
示例:
s = '''first line
second line
third line'''
# 需要從開始處匹配 所以匹配不到
print re.match('i\w+', s)
# >>> None
# 沒有限制起始匹配位置
print re.search('i\w+', s)
# >>> <_sre.SRE_Match object at 0x0000000002C6A920>
print re.search('i\w+', s).group()
# >>> irst
2.8 split(pattern, string, maxsplit=0, flags=0)
參數 maxsplit 指定切分次數, 函數使用給定正則表達式尋找切分字元串位置,返回包含切分後子串的列表,如果匹配不到,則返回包含原字元串的一個列表
示例:
s = '''first 111 line
second 222 line
third 333 line'''
# 按照數字切分
print re.split('\d+', s)
# >>> ['first ', ' line\nsecond ', ' line\nthird ', ' line']
# \.+ 匹配不到 返回包含自身的列表
print re.split('\.+', s, 1)
# >>> ['first 111 line\nsecond 222 line\nthird 333 line']
# maxsplit 參數
print re.split('\d+', s, 1)
# >>> ['first ', ' line\nsecond 222 line\nthird 333 line']
2.9 sub(pattern, repl, string, count=0, flags=0)
替換函數,將正則表達式 pattern 匹配到的字元串替換為 repl 指定的字元串, 參數 count 用於指定最大替換次數
示例:
s = "the sum of 7 and 9 is [7+9]."
# 基本用法 將目標替換為固定字元串
print re.sub('\[7\+9\]', '16', s)
# >>> the sum of 7 and 9 is 16.
# 高級用法 1 使用前面匹配的到的內容 \1 代表 pattern 中捕獲到的第一個分組的內容
print re.sub('\[(7)\+(9)\]', r'\2\1', s)
# >>> the sum of 7 and 9 is 97.
# 高級用法 2 使用函數型 repl 參數, 處理匹配到的 SRE_Match 對象
def replacement(m):
p_str = m.group()
if p_str == '7':
return '77'
if p_str == '9':
return '99'
return ' '
print re.sub('\d', replacement, s)
# >>> the sum of 77 and 99 is [77+99].
# 高級用法 3 使用函數型 repl 參數, 處理匹配到的 SRE_Match 對象 增加作用域 自動計算
scope = {}
example_string_1 = "the sum of 7 and 9 is [7+9]."
example_string_2 = "[name = 'Mr.Gumby']Hello,[name]"
def replacement(m):
code = m.group(1)
st = ''
try:
st = str(eval(code, scope))
except SyntaxError:
exec code in scope
return st
# 解析: code='7+9'
# str(eval(code, scope))='16'
print re.sub('\[(.+?)\]', replacement, example_string_1)
# >>> the sum of 7 and 9 is 16.
# 兩次替換
# 解析1: code="name = 'Mr.Gumby'"
# eval(code)
# raise SyntaxError
# exec code in scope
# 在命名空間 scope 中將 "Mr.Gumby" 賦給了變數 name
# 解析2: code="name"
# eval(name) 返回變數 name 的值 Mr.Gumby
print re.sub('\[(.+?)\]', replacement, example_string_2)
# >>> Hello,Mr.Gumby
2.10 subn(pattern, repl, string, count=0, flags=0)
作用與函數 sub 一樣, 唯一不同之處在於返回值為一個元組,第一個值為替換後的字元串,第二個值為發生替換的次數
2.11 template(pattern, flags=0)