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

模塊級別的函數

使用正則表達式也並不是必定要建立模式對象,而後調用它的匹配方法。由於,re 模塊同時還提供了一些全局函數,例如 match(),search(),findall(),sub() 等等。這些函數的第一個參數是正則表達式字符串,其餘參數跟模式對象同名的方法採用同樣的參數;返回值也同樣,一樣是返回 None 或者匹配對象。

正則表達式

  1. >>> print(re.match(r'From\s+', 'From_FishC.com'))
  2. None
  3. >>> re.match(r'From\s+', 'From FishC.com')
  4. <_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] 中的單詞,並不會匹配 'é' 或 'ç'。若是你的系統正確的設置了法語區域環境,那麼 C 語言的函數就會告訴程序 'é' 或 'ç' 也應該被認爲是一個字符。當編譯正則表達式的時候設置了 LOCALE 的標誌,\w+ 就能夠識別法文了,但速度多少會受到影響。

M
MULTILINE
^ 和 $ 咱們尚未提到,彆着急,後邊咱們有細講...)

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

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

下邊是使用 re.VERBOSE 的例子,你們看下正則表達式的可讀性是否是提升了很多:緩存

  1. charref = re.compile(r"""
  2. &[#]                # 開始數字引用
  3. (
  4.      0[0-7]+         # 八進制格式
  5.    | [0-9]+          # 十進制格式
  6.    | x[0-9a-fA-F]+   # 十六進制格式
  7. )
  8. ;                   # 結尾分號
  9. """, re.VERBOSE)
複製代碼


若是沒有設置 VERBOSE 標誌,那麼一樣的正則表達式會寫成:函數

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


哪一個可讀性更加?相信你們內心有底了。spa

相關文章
相關標籤/搜索