正则表达式:如何最好地将正则表达式与条件(在Python中)结合起来?

时间:2015-06-10 20:57:28

标签: python regex

我已经有了正则表达式(并且基于每个人使用Python re.findall()re.search()分别为IPv4地址,IPv6地址,邮件服务器提供了一些行为名称和私有IP地址。私有IP属于以下范围:

10.0.0.0 - 10.255.255.255
172.16.0.0 - 172.31.255.255
192.168.0.0 - 192.168.255.255

正则表达式;' s:

#Mail server ([a-zA-Z0-9-]+\.){2,3}[a-zA-Z]+ 
#Private IP (?:10|127|169|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168|169\.254)\..*
#IPv4       \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
#IPv6       ([a-z0-9]{1,4}:+){3,5}[a-z0-9]{1,4}

现在我需要添加一些流量控制。鉴于使用正则表达式,我们可以匹配全局,非贪婪等,组合模式等。我更喜欢利用这一事实(将正则表达式组合成单个Python表达式)而不是执行每个单独使用多个if / else' s。这是一个典型的字符串:

Received: from [192.168.0.140] (n11649196059.netvigator.com. [116.49.196.59])
        by mx.google.com with ESMTPSA id w12sm4743917pbs.68.2015.06.04.16.21.51
        for <someaddress@gmail.com>
        (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Thu, 04 Jun 2015 16:21:52 -0700 (PDT)

这里是我正在尝试做的伪代码,对于每个字符串,如上所述:

if any IPv4 or IPv6 address matches:
    if firstMatch is not private: # Private meaning matches "Private IP" regex above
        return firstMatch
    else:
         #continue through string to look for another IP address
         if found nextMatch: 
            if nextMatch is not private:
             return nextMatch
            #else continue through string to look for another IP address, 
            #again checking for privacy. If none found, just return firstMatch
    return firstMatch

# no valid IP address found, look for mail server now    
else:
    if matchedAmailServer:
        return mailServer

在上面的示例字符串中,192.168.0.140是私有的,因此我将继续执行该字符串,直到找到下一个IP地址。下一个地址是 - 116.49.196.59 - 不是私人的,所以我回来了。另一方面,如果字符串中没有第二个IP地址,我想返回mx.google.com

如何最好地智能地使用Python的re函数,以最大限度地提高正则表达式的能力并最大限度地减少if / else的数量?

1 个答案:

答案 0 :(得分:1)

如果您可以区分您感兴趣的类,只需按顺序搜索它们:

ip_addr = re.findall(RE_ADDRESSES, response)
non_private = [ x for x in ip_addr if not re.match(RE_PRIVATE, x) ]
if non_private:
    return non_private[0]
# They're all private: return first one
elif ip_addr:
    return ip_addr[0]

mailserver = re.findall(...)[0]
return mailserver

请注意,由于return终止执行,我没有使用else子句 - 这使得代码不会过于嵌套。如果您愿意,可以添加它们。