[Python] 串接正規表示式 (regular expression) 的問題

[Python] 串接正規表示式 (regular expression) 的問題

今天遇到一個奇怪的正規表示法 (regular expression) 的問題…

專案程式裡面為了方便,定義了一些簡單的 regular expression 的字串,

再用這些簡單的字串組成比較複雜的定義~

舉例來說,下面的程式定義了 letters 和 digits 兩個正規表示式,

接著用 | 把這兩個表示式連接起來變成 letters_and_digits,

表示只要符合 letters 或是 digits 的表示法都可以:

import re
letters = r'[a-zA-Z]+'
digits = r'\d+'
letters_and_digits = r'(?:letters)|(?:digits)'.replace('letters', letters).replace('digits', digits)
regex = re.compile("^%s$" % (letters_and_digits))
print regex.match("123")
print regex.match("abc")
print regex.match("abc123")

 

預期的結果是 123 是屬於 digits,abc 是屬於 letters,所以應該都是 True,

而 abc123 應該不能符合 (因為我們有指定 ^ 和 $,預期是要整個字串都符合 letters 或是都符合 digits),

但結果卻出人意料~三個敘述的結果都是 True,是怎麼一回事呢?

 

仔細看了一下,原來我們加上 ^ 和 $ 的方法有問題,

上面的寫法會變成有點像是下面這樣 (省略了 replace 的部分):

regex = re.compile("^(?:letters)|(?:digits)$")

 

這個正規表示法的意思,是開頭要符合 letters、或者是以 digits 結尾,

如果再使用 match() 的話,會強制從字串的最開頭開始比對,

因此就是要開頭要符合 letters、或是開頭到結尾都是 digits~

這樣就能解釋為什麼 “abc123” 會符合了,因為它的開頭 abc 是符合 letters 的~

 

要解決這個問題,在前面都加上 () 包住正規表示式後,再加上 ^ 和 $ 就行了,

也就是把 re.compile 那行改成:

regex = re.compile("^(%s)$" % (letters_and_digits))

 

結論:正規表示法雖然可以串接,但是要很小心呀~~

 

參考資料:python: re.match()

 

(本頁面已被瀏覽過 1,458 次)

4 thoughts on “[Python] 串接正規表示式 (regular expression) 的問題

  1. 有關 Python 『 re 』使用疑問 『 搞不懂 r 作用是什麼 』

    從妳所寫的這一篇『 [Python] 串接正規表示式 (regular expression) 的問題 』
    內文中有看到
    letters = r'[a-zA-Z]+’
    digits = r’\d+’
    letters_and_digits = r'(?:letters)|(?:digits)’.replace(‘letters’, letters).replace(‘digits’, digits)

    在 『 參考資料:python: re.match() 』
    re.VERBOSE 的範例也看到
    a = re.compile(r”””\d + # the integral part
    \. # the decimal point
    \d * # some fractional digits”””, re.X)
    b = re.compile(r”\d+\.\d*”)

    1. 主要是為了減少 escape 的問題…
      例如,假設我想要搜尋 bot 這個字,
      並且確保它是一個完整的字,而不是像 robot 這種,
      我可以用 \bbot\b,
      因為 \b 在正規表示法裡,是代表 word boundary 的意思。
      但如果你寫 “\bbot\b”,python 會認為 \b 是代表 ASCII 的 backspace
      (類似 \r, \n 這些字元都有特殊意義),
      所以你就得寫成 “\\\bbot\\\b”,不太方便。
      用 r”\bbot\b” 的話,就不需要再 escape \ 了。

  2. 收到
    ,學 CODE ,真的需要 有 先行者 幫忙
    ,就如我原本發問
    ,找了很久也沒找到 『escape 』這樣的使用解釋 ;
    放著不管 也不是 ,又不曉得 是否這就是 必須這麼使用 -_-

    謝謝妳。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料