2015年5月1日 星期五

正規表示式:描述「空白或是數字」




今天遇到一個 bug:一個用來抽取 iso 檔案並加以分析的 python script,錯誤回報說在該 iso 找不到必要的檔案 intrd.lz ,但我手動使用指令去抽取該 iso 檔,確認了裡面明明就有這個檔案。

後來發現 bug 在於以往成功提取資訊的時候,該 script 利用下面正規表示,分析下面的字串:

file_re = re.compile(

    "(?P[ldrwx-]{10})\s+\d+\s+\d+\s+\d+\s+\d+\s[A-Za-z]{3}"+ 

    "\s+\d+\s\d+\s+\[\s+\d+\s\d\d\](\s\s(?P.*))?")

其實就是這串

(?P[ldrwx-]{10})\s+\d+\s+\d+\s+\d+\s+\d+\s[A-Za-z]{3}\s+\d+\s\d+\s+\[\s+\d+\s\d\d\](\s\s(?P.*))?

去分析

-r--r--r--   1    0    0        16242610 Aug  9 2013 [ 601511 00]  initrd.lz

目的是希望可以分別找出匹配字串「-r--r--r--」與「initrd.lz」。


而出問題的是,當 script 嘗試去分析這個字串的時候,沒有得到預期的答案。

-r--r--r--   1    0    0        16437443 Nov 12 2013 [1062241 00]  initrd.lz

請注意會引起問題的字串中,有個被標示成紅色的「1」,相對於不會引起問題的字串,那個地方是個空白。所以要解決這個 bug ,只要把原本硬性描述「該空白處必須是一個或是多個空白」而使用「\s+」,換成「該地方可以是空白或是數字」。

以下兩個方法在這個問題中等價,都可以匹配出第一個 pattern 是 「-r--r--r--」而第二個是「initrd.lz」。

原本的字串:標紅色表示要被修改的部份

(?P[ldrwx-]{10})\s+\d+\s+\d+\s+\d+\s+\d+\s[A-Za-z]{3}\s+\d+\s\d+\s+\[\s+\d+\s\d\d\](\s\s(?P.*))?



解法一:改成「一個空白」加上一個星號

(?P[ldrwx-]{10})\s+\d+\s+\d+\s+\d+\s+\d+\s[A-Za-z]{3}\s+\d+\s\d+\s+\[ *\d+\s\d\d\](\s\s(?P.*))?



解法二:注意「0-9」的前面也有一個空白,使用數字 5、8 是給實際數字位數一點容忍量,在這個案例中,一個 7 就夠用了。

(?P[ldrwx-]{10})\s+\d+\s+\d+\s+\d+\s+\d+\s[A-Za-z]{3}\s+\d+\s\d+\s+\[[ 0-9]{5,8}\s\d\d\](\s\s(?P.*))?



附錄資料:

  • 好用的線上正規表示式解讀器;若完全只用人腦翻譯真的實在太辛苦了。
  • https://atedev.wordpress.com/2007/11/23/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%A4%BA%E5%BC%8F-regular-expression/
  • http://notepad.yehyeh.net/Content/Program/RegularExpression/8.php
  • http://zh.wikipedia.org/wiki/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F
  • http://stackoverflow.com/questions/18701992/regex-space-or-no-space
  • python 2 的 re module 說明文件
  • 簡易語法參考:
    • \s 一個空白,\s+ 多個空白
    • \d 一個數字,\d+ 多個數字
    • \[ 跳脫字元和一個「[」,表示我想要匹配「[」
    • * 星號表示星號前面的元素有沒有出現、而且可以出現多次。一個空白加一個星號就是「有沒有空白無所謂,也可以有多個空白」
    • [ 0-9]{5,8}  允許一個空白(注意 0 前面有個空白)、數字零到九,並且只匹配出現那樣的元素 5 到 8 個。


沒有留言:

張貼留言