re 模組


在 Python 中,使用 re 模組來支援規則表示式。例如,若想切割字串,可以使用 re.split 函式:

>>> import re
>>> re.split(r'\d', 'Justin1Monica2Irene')
['Justin', 'Monica', 'Irene']
>>> re.split(r',', 'Justin,Monica,Irene')
['Justin', 'Monica', 'Irene']
>>> re.split(r'Orz', 'JustinOrzMonicaOrzIrene')
['Justin', 'Monica', 'Irene']
>>> re.split(r'\t', 'Justin\tMonica\tIrene')
['Justin', 'Monica', 'Irene']

re 模組的 split 函式,第一個參數要以字串來指定規則表示式,實際上若使用 Python 的字串表示時,因為 \ 等在Python字串中被作為轉義(Escape)字元,因此要撰寫規則表示式時,例如 \d,就必須撰寫為 '\\d',這樣當然很麻煩。

幸而 Python 中可以在字串前加上 r,表示這是個原始字串(Raw string),不要對 \ 做任何轉義動作,因此在撰寫規則表示式時,建議使用原始字串。

如果想找出字串中全部符合表示式的文字,可以使用 re.findall 函式,結果會以 list 傳回,若沒有符合就是傳回空 list

例如來實際看看貪婪量詞(Greedy quantifier)與逐步量詞(Reluctant quantifier)的差別:

>>> re.findall(r'.*foo', 'xfooxxxxxxfoo')
['xfooxxxxxxfoo']
>>> re.findall(r'.*?foo', 'xfooxxxxxxfoo')
['xfoo', 'xxxxxxfoo']

例如分別比對出來的名稱最後必須有或沒有 'Lin'

>>> re.findall(r'\w+\s(?=Lin)', 'Justin Lin, Monica Huang, Irene Lin')
['Justin ', 'Irene ']
>>> re.findall(r'\w+\s(?!Lin)', 'Justin Lin, Monica Huang, Irene Lin')
['Monica ']

如果要取代符合的子字串,可以使用 re.sub 函式。例如,將所有單引號都換成雙引號:

>>> re.sub("'", '"', "your right brain has nothing 'left' and your left brain has nothing 'right'")
'your right brain has nothing "left" and your left brain has nothing "right"'

如果規則表示式中有分組設定,在使用 sub 時,可以使用 \num 來捕捉被分組匹配的文字,num 表示第幾個分組。

例如,以下示範如何將使用者郵件位址從 .com 取代為 .cc:

>>> re.sub(r'(^[a-zA-Z]+\d*)@([a-z]+?.)com', r'\1@\2cc', 'caterpillar@openhome.com')
'caterpillar@openhome.cc'

整個規則表示式匹配了 'caterpillar@openhome.com',第一個分組捕捉到 'caterpillar',第二個分組捕捉到 'openhome.'\1\2 就分別代表這兩個部份。

如果使用了 (?P<name>…) 為分組命名,在呼叫 sub 函式時,必須使用 \g<name> 來參考。例如:

>>> re.sub(r'(?P<user>^[a-zA-Z]+\d*)@(?P<preCom>[a-z]+?.)com', r'\g<user>@\g<preCom>cc', 'caterpillar@openhome.com')
'caterpillar@openhome.cc'

re.sub 會將全部符合的文字都進行取代,傳回取代後的字串,re.subnre.sub 功能相同,然而傳回一個 Tuple,第一個元素是取代後的字串,第二個是符合的文字數量:

>>> re.sub(r'\d\d', 'Orz', '12dd1232')
'OrzddOrzOrz'
>>> re.subn(r'\d\d', 'Orz', '12dd1232')
('OrzddOrzOrz', 3)

在〈〉中談過,詮譯字元在規則表示式中有特殊意義,例如 $ ^ * ( ) + = { } [ ] | \ : . ? 等,若要比對這些字元,則必須加上轉義(Escape)符號,即使 Python 有原始字串表示,自己處理這些事也還是麻煩,這時可以使用 re.escape 來代勞:

>>> re.escape(r'python.exe')
'python\\.exe'