Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Brief Introduction to Regular Expression with Python 2.7.3 Standard Library

A Brief Introduction to Regular Expression with Python 2.7.3 Standard Library

2014/Jul/08: 修改Lookahead/Lookbehind說明
2014/Jun/28: 修正錯誤
2014/Jun/18: 修正Lookahead assertion和Lookbehind assertion寫反的錯誤

Wen_Liao

June 16, 2014
Tweet

More Decks by Wen_Liao

Other Decks in Technology

Transcript

  1. Goal • 以Python 2.7.3 Standard Library為範例簡介 Regular Expression (簡稱為re/regex) •

    範例大部分使用re.match(),少部份用re. search(),更少部份使用re.sub()和re.findall() ◦ re.search()和re.findall()是只取得符合的部份。 ▪ print re.search(“test”, "test_whatever").group() test ▪ print re.findall("test", "test54 test_2 test_whatever") ['test', 'test', 'test']
  2. Outline • 概論 • 測試環境設定 • 有效的字元 • Qualifiers •

    Groups • Assertion • 總結 • 參考資料 • Q & A
  3. • 範例 ◦ 身份證號碼: ▪ 大寫英文字母開頭,之後連接九個數字 ◦ 電子郵件信箱: ▪ 由使用者和主機名稱組成,中間以@隔開

    ▪ 使用者名稱 • 可以由數字, 英文句號和英文組合 • 使用者名稱最長為63 bytes • … ▪ 主機名稱: • 以英文句號隔開的字串 • 最後一個字元不得為英文句號 • …
  4. Regex和我有什麼關係? • 有了描述方法後,可以 ◦ 從大量文字中找出符合描述的字串 ▪ 取代 ▪ 產生報表 ◦

    判斷字串是否合於規定? ◦ 切割字串 • 範例: ◦ 找出目錄中所有變數my_var被設定的檔案 ◦ 把檔案中的巨集加上MY_DEF prefix ◦ 撈出百萬行訊息中發生錯誤的來源IP ◦ 判斷使用者輸入的email是否型式正確 ◦ ...
  5. 有效的單獨字元 • 任何字元 • 多選一 ◦ 範例: + - *

    / 其中一個 • 範圍 ◦ 範例: 0到9, A到Z • 排除 ◦ 範例: 除了* 以外任何字元 • 單一特定字元 ◦ 範例: A
  6. 有效的字元組合而成的順序 • 範例 ◦ 單一特定位元組合字串 ▪ Linux ▪ Pork belly

    ◦ 有效字元組合字串 ▪ 任何字母 空白 = 空白 數字 數字; • a = 10; • c = 66; ▪ 五個英文字母後面接三個數字 • abcde123 • Linux769 • Belly007
  7. 檢查目前字元位置是否符合描述的條件 • 每行開頭為A ◦ App ◦ Ace • 每行結尾為! ◦

    Bad! ◦ GG! • 空白字元位置前面要是This ◦ This cat ◦ This one • 空白字元位置後面要是over ◦ oh over ◦ game over
  8. 撒尿牛丸 • 以<a開頭 /a>結尾 • 中間要name, =, 有一對””, “”中間有任意長度 的數字或英文字母

    • 並且=前後可以有任意個空白 ◦ < a name = “wen” /a> ◦ < a name = “regex” /a>
  9. Outline • 概論 • 測試環境設定 • 有效的字元 • Qualifiers •

    Groups • Assertion • 總結 • 參考資料 • Q & A
  10. $ ipython Python 2.7.3 (default, Feb 27 2014, 19:58:35) ...

    IPython 0.12.1 -- An enhanced Interactive Python. … In [1]: import re
  11. Outline • 概論 • 測試環境設定 • 有效的字元 • Qualifiers •

    Groups • Assertion • 總結 • 參考資料 • Q & A
  12. 多選一 • [字元一字元二字元三...] ◦ [abcdefghijklmnopqurstuvwxyz] ◦ [0123456789] ◦ [-+*/] •

    範例 print re.match(r'[012345789]', "0").group() 0 print re.match(r'[012345789]', "a") None - 有特殊意義,做為 一般字元請放第一位
  13. 範圍 • [起始字元(ASCII值小)-結束字元(ASCII值大)] ◦ [0-9] ◦ [a-z] ◦ [S-T] •

    範例 print re.match(r"[0-9]", "0").group() 0 print re.match(r"[0-9]", "a") None
  14. 特殊字元 特殊字元 描述行為說明 特殊字元 描述行為說明 \A 字串開頭 \s 分隔字元 [

    \t\n\r\f\v] \b 字母或數字前面或後 面是否為分隔字元 (後面說明) \S 非分隔字元 [^ \t\n\r\f\v] \B 是否為字母或數字中 的一部份 (後面說明) \w 字母或數字 [a-zA-Z0-9_] \d 數字 [0-9] \W 非字母也不是數字 [^a-zA-Z0-9_] \D 非數字 [^0-9] \Z 字串結尾
  15. 任意字元 • . ◦ 不包含跳行符號 • [\s\S] print re.match(r".", "\n")

    None print re.match(r"[\s\S]", "\n") <_sre.SRE_Match object at 0x132d920>
  16. Outline • 概論 • 測試環境設定 • 有效的字元 • Qualifiers •

    Groups • Assertion • 總結 • 參考資料 • Q & A
  17. Qualifiers 符號 描述行為說明 範例 {次數m} 字元出現m次 ac{3} ---> accc {次數m,

    次數n} 字元出現m到n次 ac{1, 2} ---> ac或acc * 字元不出現或是出現任意 次 ac* -> a, accccccc + 字元出現一次以上 ac+ -> ac, accccc ? 字元不出現或是出現一次 ac? -> a, ac
  18. Greedy Qualifier說明 • Regex engine遇到.*或.+會一直比對到字串結 束的地方。 • 比對到字串結束的地方,會backtrack之前的字 元,再比對後面的描述。 ◦

    regex: <.*> v.s. <tags>>> ◦ <tags>>> <.* 比對成立一路到底,backtrack一個字元,該 值為>。 > 符合<.*>的最後預期字元的描述,所以字串 符合regex的描述。 參考: http://www.perlmonks.org/? node_id=390117
  19. 怎麼辦? • 在qualifier後面加?告訴regex engine不要用 greedy qualifier print re.match(r'<.*?>', "<tags>>>").group() <tags>

    • <>中間不允許出現>字元 print re.search(r'<[^>]*>', "<tags>>>").group() <tags>
  20. Outline • 概論 • 有效的字元 • Qualifiers • Groups ◦

    Reference ◦ Alternation • Assertion • 總結 • 參考資料 • Q & A
  21. Group • 以小括號組合有效字元提供regex engine 比 對。 • 範例: ◦ regex:

    (I am ).* ▪ I am Wen. ▪ I am whatsoever print re.match(r'(I am ).*', "I am") None print re.match(r'(I am ).*', "I am Wen.").group() I am Wen. 沒有空白
  22. Outline • 概論 • 有效的字元 • Qualifiers • Groups ◦

    Reference ◦ Alternation • Assertion • 總結 • 參考資料 • Q & A
  23. 姓名表示方式: 西方 v.s. 東方 ex: Wen Liao v.s. Liao, Wen

    print re.sub(r'(\w+)\s(\w+)', r'\2, \1', "Wen Liao") Liao, Wen 字串取代的API,用 \1\2代表第1、第2組 group
  24. Outline • 概論 • 有效的字元 • Qualifiers • Groups ◦

    Reference ◦ Alternation • Assertion • 總結 • 參考資料 • Q & A
  25. Outline • 概論 • 有效的字元 • Qualifiers • Groups •

    Assertion ◦ Anchor ◦ Lookahead Assertion和Lookbehind Assertion • 總結 • 參考資料 • Q & A
  26. Assertion • Longman: assert ◦ to state firmly that something

    is true ▪ http://www.ldoceonline.com/dictionary/assert ◦ 堅定地表達特定事物為真的事實 • 表達立場,所以要驗證是否唬爛 ◦ 一種測試
  27. Regex的Assertion • 測試目前parse到的字元位置 ◦ 前面是否符合特定條件,或是 ◦ 後面是否符合特定條件 • parse位置不會移動 ◦

    之前的「字串描述」,滿足條件regex engine會parse目 標字串的下一個字元。 ◦ ex: ▪ regex: linux ▪ string: linux • 第一次l滿足,第二次比對l下一個字元是不是i
  28. 表示符號 描述行為說明 範例 \A 字串開頭 \Ahi.* \Z 不包含跳行符號的字串結尾 .*over\n\Z ,

    .*over\Z ^ 字串開頭 ^hi.* $ 字串結尾,等於(\Z|\n\Z) .*over$ \b 字母或數字前面或後面是否為分隔字元 \bcon\b \B 是否為字母或數字中的一部份 \Bcon\B (?=regex) 目前字元位置後面是否滿足regex (?=over) (?!regex) 目前字元位置後面是否不是regex (?!start) (?<=regex) 目前字元位置前面是否滿足regex (?<=over) (?<!regex) 目前字元位置前面是否不是regex (?<!start) 有哪些特定條件呢?
  29. Outline • 概論 • 有效的字元 • Qualifiers • Groups •

    Assertion ◦ Anchor ◦ Lookahead Assertion和Lookbehind Assertion • 總結 • 參考資料 • Q & A
  30. Anchor 表示符號 描述行為說明 範例 \A 字串開頭 \Ahi.* \Z 不包含跳行符號的字串結尾 .*over\n\Z

    , .*over\Z ^ 字串開頭 ^hi.* $ 字串結尾,等於(\Z|\n\Z) .*over$ \b 字母或數字前面或後面是否為分隔字元 \bcon\b \B 是否為字母或數字中的一部份 \Bcon\B (?=regex) 目前字元位置後面是否滿足regex 稍候再談 (?!regex) 目前字元位置後面是否不是regex 稍候再談 (?<=regex) 目前字元位置前面是否滿足regex 稍候再談 (?<!regex) 目前字元位置前面是否不是regex 稍候再談
  31. $: 範例 print re.search(r'test.*over$', "test over123\n") None print re.search(r'test.*over', "test

    over123\n").group() test over 字串結束字元為 跳行符號\n 不包含跳行符號 的字串結束位置
  32. \Z: 範例 print re.search(r'test.*over\Z', "test over\n") None print re.search(r'test.*over\n\Z', "test

    over\n").group() test over 字串結束字元為 跳行符號\n 包含跳行符號的 字串結束位置 必須要明確指定\n
  33. \Z和$的差別 # 多行模式下$還可以提供多次搜尋而\Z仍然是字串結尾 print re.findall(r'(?m)test.*over$', "test over\ntest is over\n") ['test

    over', 'test is over'] print re.findall(r'(?m)test.*over\n\Z', "test over\ntest is over\n") ['test is over\n'] 多行模式,請 自行參考手冊
  34. \A和^的差別 # 多行模式下^還可以提供多次搜尋而\A仍然是字串開頭 print re.findall(r'(?m)^test.*', "test_1\ntest_2") ['test_1', 'test_2'] print re.findall(r'(?m)\Atest.*',

    "test_1\ntest_2") ['test_1'] 字串起始位置 字串起始位置 跳行符號 跳行符號 多行模式,請 自行參考手冊
  35. \b範例 (b for boundary) # 用來區別是否是一個word print re.findall(r'\btest\b', "test test_whatever")

    ['test'] print re.findall(r'test\b', "test test_whatever") ['test'] print re.findall(r'\btest', "test test_whatever") ['test', 'test']
  36. Outline • 概論 • 有效的字元 • Qualifiers • Groups •

    Assertion ◦ Anchor ◦ Lookahead Assertion和Lookbehind Assertion • 總結 • 參考資料 • Q & A
  37. 表示符號 描述行為說明 範例 \A 字串開頭 \Ahi.* \Z 不包含跳行符號的字串結尾 .*over\n\Z ,

    .*over\Z ^ 字串開頭 ^hi.* $ 字串結尾,等於(\Z|\n\Z) .*over$ \b 字母或數字前面或後面是否為分隔字元 \bcon\b \B 是否為字母或數字中的一部份 \Bcon\B (?=regex) 目前字元位置後面是否滿足regex (?=over) (?!regex) 目前字元位置後面是否不是regex (?!start) (?<=regex) 目前字元位置前面是否滿足regex (?<=over) (?<!regex) 目前字元位置前面是否不是regex (?<!start) Lookahead Assertion Lookbehind Assertion
  38. Lookahead Assertion • 目前字元後面是否符合特定條件 ◦ 後面條件成立才繼續比對 ▪ (?=成立條件描述) ◦ 後面條件不成立才繼續比對

    ▪ (?!不成立條件描述) • 範例 ◦ 字串前面必須要有file ▪ unittest_file, src_file, ... ◦ 字串後面不得出現test
  39. Lookbehind Assertion • 目前字元前面是否符合特定條件 ◦ 前面條件成立才繼續比對 ▪ (?<=成立條件描述) ◦ 前面條件不成立才繼續比對

    ▪ (?<!不成立條件描述) • 範例 ◦ 字串前面必須要有unittest ▪ unittest_file1, unittest_cases, ... ◦ 字串前面不得出現fake
  40. 前情提要:Regex的Assertion • 測試目前parse到的字元位置 ◦ 前面是否符合特定條件,或是 ◦ 後面是否符合特定條件 • parse位置不會移動 ◦

    之前的「字串描述」,滿足條件regex engine會parse目 標字串的下一個字元。 ◦ ex: ▪ regex: linux ▪ string: linux • 第一次l滿足,第二次比對l下一個字元是不是i
  41. 小結 • Assert parse位置不會移動不是喊假的 • 難道下lookahead assertion都要算前面吃幾 個字元? ◦ match()需要

    ◦ search(), sub(), findall()不用 ▪ re.search(pattern, string, flags=0) • Scan through string looking for the first location where the regular expression pattern produces a match • 窮舉檢視字串所有字元,直到找到第一個符合Regex的結果為 止。 https://docs.python.org/2/library/re.html
  42. Outline • 概論 • 測試環境設定 • 有效的字元 • Qualifiers •

    Groups • Assertion • 總結 • 參考資料 • Q & A
  43. 上面描述的排列組合 • \ADear[\s\S]*\nBest regards,\nWen Liao\Z Dear Sir,\nFirst at all, I

    would like to ..(下略500 字)\nBest regards,\nWen Liao . 不包含換行 符號!
  44. 這只是簡介,還有興趣的可以去了解 • NFA • Regex modes • Re APIs (re.comple()...etc)

    • Unicode和Regex的關係 • 描述方式和效率的關係 ◦ Disable capturing group ◦ 安全問題: ReDoS • 流派 ◦ PCRE ◦ POSIX: BRE, ERE, SRE • ...
  45. Outline • 概論 • 測試環境設定 • 有效的字元 • Qualifiers •

    Groups • Assertion • 總結 • 參考資料 • Q & A
  46. 參考資料 • The Python Standard Library: re ◦ https://docs.python.org/2/library/re.html •

    Regular Expression HOWTO ◦ https://docs.python.org/2/howto/regex.html • PHP: Assertions - Manual ◦ http://php.net/manual/en/regexp.reference. assertions.php • 處理大數據的必備美工刀 - 全支援中文的正規 表示法精解 ◦ http://www.grandtech.info/02-shop-detail-53-824. html
  47. Outline • 概論 • 測試環境設定 • 有效的字元 • Qualifiers •

    Groups • Assertion • 總結 • 參考資料 • Q & A