1. 程式人生 > >Python3 如何優雅地使用正則表示式(詳解三)

Python3 如何優雅地使用正則表示式(詳解三)

上一篇:Python3 如何優雅地使用正則表示式(詳解二)

模組級別的函式

使用正則表示式也並非一定要建立模式物件,然後呼叫它的匹配方法。因為,re 模組同時還提供了一些全域性函式,例如 match(),search(),findall(),sub() 等等。這些函式的第一個引數是正則表示式字串,其他引數跟模式物件同名的方法採用一樣的引數;返回值也一樣,同樣是返回 None 或者匹配物件。

>>> print(re.match(r'From\s+', 'From_FishC.com'))
None
>>> re.match(r'From\s+', 'From FishC.com')
<_sre.SRE_Match object; span=(0, 5), match='From '>

其實,這些函式只是幫你自動建立一個模式物件,並呼叫相關的函式(上一篇的內容,還記得嗎?)。它們還將編譯好的模式物件存放在快取中,以便將來可以快速地直接呼叫。

那我們到底是應該直接使用這些模組級別的函式呢,還是先編譯一個模式物件,再呼叫模式物件的方法呢?這其實取決於正則表示式的使用頻率,如果說我們這個程式只是偶爾使用到正則表示式,那麼全域性函式是比較方便的;如果我們的程式是大量的使用正則表示式(例如在一個迴圈中使用),那麼建議你使用後一種方法,因為預編譯的話可以節省一些函式呼叫。但如果是在迴圈外部,由於得益於內部快取機制,兩者效率相差無幾。

 

編譯標誌

編譯標誌讓你可以修改正則表示式的工作方式。在 re 模組下,編譯標誌均有兩個名字:完整名和簡寫,例如 IGNORECASE 簡寫是 I(如果你是 Perl 的粉絲,那麼你有福了,因為這些簡寫跟 Perl 是一樣的,例如 re.VERBOSE 的簡寫是 re.X)。另外,多個標誌還可以同時使用(通過“|”),如:re.I | re.M 就是同時設定 I 和 M 標誌。



下邊列舉一些支援的編譯標誌:
 

標誌 含義
ASCII, A 使得轉義符號如 \w,\b,\s 和 \d 只能匹配 ASCII 字元
DOTALL, S 使得 . 匹配任何符號,包括換行符
IGNORECASE, I 匹配的時候不區分大小寫
LOCALE, L 支援當前的語言(區域)設定
MULTILINE, M 多行匹配,影響 ^ 和 $
VERBOSE, X (for 'extended') 啟用詳細的正則表示式


下面我們來詳細講解一下它們的含義:

A
ASCII
使得 \w,\W,\b,\B,\s  \S 只匹配 ASCII 字元,而不匹配完整的 Unicode 字元。這個標誌僅對 Unicode 模式有意義,並忽略位元組模式。

S
DOTALL
使得 . 可以匹配任何字元,包括換行符。如果不使用這個標誌,. 將匹配除了換行符的所有字元。

I
IGNORECASE
字元類和文字字串在匹配的時候不區分大小寫。舉個例子,正則表示式 [A-Z] 也將會匹配對應的小寫字母,像 FishC 可以匹配 FishCfishc 或 FISHC 等。如果你不設定 LOCALE,則不會考慮語言(區域)設定這方面的大小寫問題。

L
LOCALE
使得 \w,\W,\b 和 \B 依賴當前的語言(區域)環境,而不是 Unicode 資料庫。

區域設定是 C 語言的一個功能,主要作用是消除不同語言之間的差異。例如你正在處理的是法文文字,你想使用 \w+ 來匹配單詞,但是 \w 只是匹配 [A-Za-z] 中的單詞,並不會匹配 'é' 或 '&#231;'。如果你的系統正確的設定了法語區域環境,那麼 C 語言的函式就會告訴程式 'é' 或 '&#231;' 也應該被認為是一個字元。當編譯正則表示式的時候設定了 LOCALE 的標誌,\w+ 就可以識別法文了,但速度多少會受到影響。

M
MULTILINE
^ 和 $ 我們還沒有提到,彆著急,後邊我們有細講...)

通常 ^ 只匹配字串的開頭,而 $ 則匹配字串的結尾。當這個標誌被設定的時候,不僅匹配字串的開頭,還匹配每一行的行首;& 不僅匹配字串的結尾,還匹配每一行的行尾。

X
VERBOSE
這個標誌使你的正則表示式可以寫得更好看和更有條理,因為使用了這個標誌,空格會被忽略(除了出現在字元類中和使用反斜槓轉義的空格);這個標誌同時允許你在正則表示式字串中使用註釋,符號後邊的內容是註釋,不會遞交給匹配引擎(除了出現在字元類中和使用反斜槓轉義的 #)。

下邊是使用 re.VERBOSE 的例子,大家看下正則表示式的可讀性是不是提高了不少:

charref = re.compile(r"""
&[#]                # 開始數字引用
(
     0[0-7]+         # 八進位制格式
   | [0-9]+          # 十進位制格式
   | x[0-9a-fA-F]+   # 十六進位制格式
)
;                   # 結尾分號
""", re.VERBOSE)

如果沒有設定 VERBOSE 標誌,那麼同樣的正則表示式會寫成:

charref = re.compile("&#(0[0-7]+|[0-9]+|x[0-9a-fA-F]+);")

哪個可讀性更加?相信大家心裡有底了。

(未完待續)

下一篇:Python3 如何優雅地使用正則表示式(詳解四)