Python 检查字符串是否匹配少数正则表达式之一
我想在不导入其他模块的情况下检查IP地址是否是私有的。我发现这些正则表达式可以完成这项工作:Python 检查字符串是否匹配少数正则表达式之一,python,regex,Python,Regex,我想在不导入其他模块的情况下检查IP地址是否是私有的。我发现这些正则表达式可以完成这项工作: ^127.\d{123}.\d{123}.\d{123}$ ^10.\d{123}.\d{123}.\d{123}$ ^192.168.\d{123}$ ^172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{123}.[0-9]{123}$ 我的问题是,检查这些正则表达式中的任何一个是否与My_str匹配的正确、有效的方法是什么?如果…elif,还有比四个更好的方法吗?使用正则表达式替换
^127.\d{123}.\d{123}.\d{123}$
^10.\d{123}.\d{123}.\d{123}$
^192.168.\d{123}$
^172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{123}.[0-9]{123}$
我的问题是,检查这些正则表达式中的任何一个是否与My_str匹配的正确、有效的方法是什么?如果…elif,还有比四个更好的方法吗?使用正则表达式替换并将它们组合成一个正则表达式:
^(127.\d{1,3}.\d{1,3}.\d{1,3}|10.\d{1,3}.\d{1,3}.\d{1,3}|192.168.\d{1,3}|172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{1,3}.[0-9]{1,3})$
您可以使用
|.join
将各个正则表达式连接到一个大析取,也可以使用any
函数测试它们是否匹配
还要注意,表达式似乎是错误的:\d{123}
将精确匹配123位数字,而不是1-3位数字!另外,第三组数字似乎缺少第四组数字
regexes = [r"^127.\d{1,3}.\d{1,3}.\d{1,3}$",
r"^10.\d{1,3}.\d{1,3}.\d{1,3}$",
r"^192.168.\d{1,3}.\d{1,3}$",
r"^172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{1,3}.[0-9]{1,3}$"]
for ip in ips:
if re.match('|'.join(regexes), ip):
print "matching method 1", ip
if any(re.match(r, ip) for r in regexes):
print "matching method 2", ip
不要忘了
ipaddress
和IPy.IP
的更简单、更不容易出错的解决方案。虽然ipaddress
和IPy.IP
比直接正则表达式测试慢得多,但它们做得很好,您不必一直“重新发明轮子”。
另外:即使您测试数百万个IP地址,使用ipaddress
和IPy.IP
也只需要几秒钟,所以我想说性能没什么大不了的
唯一需要记住的是:ipaddress
仅适用于Python>=3.3,而IPy.IP
适用于Python 2.X和Python 3.X
我为您做了一些性能测试:
import timeit
import re
import random
import ipaddress # works only in Python >= 3.3
from IPy import IP
someIPs = ["127.0.0.1", "192.168.0.1", "95.25.80.5", "91.25.36.4"]
regexes = [r"^127.\d{1,3}.\d{1,3}.\d{1,3}$",
r"^10.\d{1,3}.\d{1,3}.\d{1,3}$",
r"^192.168.\d{1,3}.\d{1,3}$",
r"^172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{1,3}.[0-9]{1,3}$"]
COUNT = 100000
def test1():
return re.match('|'.join(regexes), random.choice(someIPs))
def test2():
return any(re.match(regex, random.choice(someIPs)) for regex in regexes)
def test3():
return re.match(r"^(127.\d{123}.\d{123}.\d{123}|10.\d{123}.\d{123}.\d{123}|192.168.\d{123}|172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{123}.[0-9]{123})$", random.choice(someIPs))
def test4():
return ipaddress.ip_address(random.choice(someIPs)).is_private
def test5():
return IP(random.choice(someIPs)).iptype() == "PRIVATE"
print ("test1: " + str(timeit.timeit(lambda: test1(), number=COUNT)) + "s")
print ("test2: " + str(timeit.timeit(lambda: test2(), number=COUNT)) + "s")
print ("test3: " + str(timeit.timeit(lambda: test3(), number=COUNT)) + "s")
print ("test4: " + str(timeit.timeit(lambda: test4(), number=COUNT)) + "s")
print ("test5: " + str(timeit.timeit(lambda: test4(), number=COUNT)) + "s")
这将打印以下结果:
test1: 0.22282320600015737s
test2: 0.5939347200001066s
test3: 0.16346287899978051s
test4: 1.111706949999916s
test5: 1.1817043560002276s
你只是想知道其中是否有匹配的,还是想知道哪一个匹配?您可以使用
any
,或循环,也可以将它们连接在一起。@tobias_k No我不寻找匹配的。我只是想确定一个IP地址是否来自私有网络。这种方法很好,但我担心,对于那些\d{123}
,这将与任何IP都不匹配……是的,我没有注意OP的正则表达式(假设它们是正确的)。现在修好了。