攝影:產品經理
下廚:kingname
如今我有10億條微博正文,並從同事手上拿到了15000條須要過濾的垃圾信息正則表達式,只要微博正文符合任何一條正則表達式,就刪除這條微博。web
正則表達式的格式爲:正則表達式
^你成功領取 |^感謝您的積 |^在第\d+次抽獎. |^只有幫主才 |^目標有相應 |^寶寶#G. |^提交失敗, |^您已領取過 |^破軍爭奪戰 |^首席大弟子 |數第\d+個丫環 |你的店鋪 |恭喜.*?投中了 |<web |你將該物品拆解成 |^你身上沒有 |歡迎參加微博抽獎 |蔡徐坤 |王一博 |朱一龍 ...
存放在一個名爲trash.txt的文本文件中,每一個正則表達式一行。ide
通常狀況下,我只須要使用以下幾行代碼就能實現這個功能:code
import re with open('trash.txt', encoding='utf-8') as f: lines = [x.strip() for x in f] pattern = re.compile(''.join(lines)) for weibo in weibo_list: if pattern.search(weibo): print('垃圾信息,過濾!')
可是當個人代碼運行到re.compile這一行時,報錯了,以下圖所示:blog
而且,即便你在 Google 上面搜索:re.error: multiple repeat at position,截至2019年12月30日,你能找到的都是對這個報錯的討論,但沒有一個討論能解決本文描述的問題。ip
那咱們自食其力,來試着解決一下這個問題。它報錯報的是position 167,那麼咱們來看看第167個字符有什麼問題。在 PyCharm 中,能夠在右下角查看你選中了多少個字符,以下圖所示:utf-8
從截圖中能夠看到,第167個字符所在的這一行正則表達式爲:|張三丰.?張翠山.?張無忌,可是我徹底看不出這一行正則表達式有什麼問題。產品
因爲報錯了,那麼確定至少有一行正則表達式有問題,咱們假設有問題的正則表達式有且只有一行。如今咱們有15000行正則表達式,如何找出有問題的這一行呢?it
這個時候,咱們就可使用二分查找來解決這個問題,,咱們最多查找14次就能找到有問題的這一行正則表達式。io
因爲正則表達式一共有15000行,咱們就先看0-7500行在編譯時是否會報錯,若是報錯,在看0-3750行是否報錯,若是不報錯,在看3750-7500行是否報錯……如此分割下去,直到找到報錯的這一行正則表達式。
二分查找的代碼以下:
import re with open('trash.txt', encoding='utf-8') as f: lines = [x.strip() for x in f] def is_compile_success(regex): try: re.compile(regex) return True except Exception: return False def search(regex_list): if len(regex_list) == 1: print(regex_list[0]) return mid = len(regex_list) // 2 part_1 = ''.join(regex_list[: mid]) part_2 = ''.join(regex_list[mid: ]) if not is_compile_success(part_1): search(regex_list[: mid]) return if not is_compile_success(part_2): search(regex_list[mid:]) return search(lines)
運行結果以下圖所示:
原來出問題的地方在:.??,這裏多寫了一個問號。把這一行改爲|趙大.?包之後,編譯成功經過。
思考題
若是要把出問題的這一行所在的行號打印出來,應該如何修改代碼?
若是有問題的正則表達式不止一行,應該如何修改代碼,從而打印全部有問題的正則表達式?