Python最大执行时间或加速正则表达式

时间:2016-07-18 03:01:08

标签: python regex

我有一个正则表达式匹配器,用于检查Python中的Web流量。问题是,有时,如果页面大于1MB并且由单个字符串组成,则正则表达式将永远完成。我想知道是否有办法设置最大执行超时?

我的脚本从文件中读取正则表达式,然后一次处理一个:

def match_keywords_add_to_es(pastes):
    match_list = get_re_match_list()
    for paste in pastes:
        log.info("matching %s"%paste["key"])
        for match in match_list:
            matched = match[1].findall(paste["raw"].lower())
            if len(matched) > 0:
                try:
                    paste["keywords"] = match[0]
                    res_paste = Paste(dictionary=paste)
                    Paste.add_paste(res_paste)
                except Exception,e:
                    log.error("Failed to add the paste "+str(paste)+" with error %s"%e)

示例正则表达式:

secret_key:
  match: .*secret(_)?key\s*=\s*(.*)?[A-Za-z0-9\/]{40}(.*)?.*

access_key:
  match: .*access(_)?key\*=\*(.*)?[A-Z0-9]{20}(.*)?.*

example.com:
    match: .*example\.com.*

1 个答案:

答案 0 :(得分:3)

我将专注于你的一个regexen的这一部分:

\s*(.*)?[A-Za-z0-9\/]{40}(.*)?.*

首先,\s*(.*)?。这样做的问题是\s*可以反刍空白,然后由(.*)?消耗(问号也是不必要的)。结果是,如果你的正则表达式得到这么多,你会得到很多完全无用的回溯,但是在其余的那一行上却无法匹配。您可能希望使用比.更严格的内容,强制\s尽可能多地匹配空格,并拒绝再次放弃它们:

\s*(\S.*|)

这匹配一个非空白字符后跟任何内容或空字符串。它不能消耗由\s反刍的空白,因此你的回溯会减少痛苦。

向前跳过,这种结构完全莫名其妙:(.*)?.*。第一个点星将消耗该行上的所有剩余字符,因此您不需要第二个。 Star也可以匹配零次,因此在这种情况下你也不需要问号。

您也无需逃避/,正如WiktorStribiżew在评论中指出的那样。

因此修改后的片段如下所示:

\s*(\S.*|)[A-Za-z0-9/]{40}(.*)

作为最后一点,我建议让(.*)个序列中的一个(并且只有一个)变得懒惰,因为我发现很难判断你是否会抓住第一个部分匹配[A-Za-z0-9\/]{40}的行或匹配的行的最后部分。我相信让第二个懒惰不会改变正则表达式的含义,但我不是100%肯定这一点,所以一定要测试它。