一日一技:使用二分法排查正則表達式的異常

一日一技:使用二分法排查正則表達式的異常

一日一技:使用二分法排查正則表達式的異常

攝影:產品經理
下廚: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)

運行結果以下圖所示:
一日一技:使用二分法排查正則表達式的異常

原來出問題的地方在:.??,這裏多寫了一個問號。把這一行改爲|趙大.?包之後,編譯成功經過。

思考題

若是要把出問題的這一行所在的行號打印出來,應該如何修改代碼?
若是有問題的正則表達式不止一行,應該如何修改代碼,從而打印全部有問題的正則表達式?

一日一技:使用二分法排查正則表達式的異常

相關文章
相關標籤/搜索