Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 检查字符串是否匹配少数正则表达式之一_Python_Regex - Fatal编程技术网

Python 检查字符串是否匹配少数正则表达式之一

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,还有比四个更好的方法吗?使用正则表达式替换

我想在不导入其他模块的情况下检查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{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的正则表达式(假设它们是正确的)。现在修好了。