我需要检查字符串是否有任何IPv4地址或以下CIDR块之一:/ 16或/ 24。 所以,192.168.0.1应该匹配。 192.168.0.0/16应匹配。 192.168.0.0/17不匹配 我正在使用以下正则表达式:
re.compile(r'^([0-9]{1,3}\.){3}[0-9]{1,3}(/(16|24))?')
这匹配所有IP地址,但也匹配192.168.0.0/aaaa
等字符串现在,如果我更改正则表达式(删除?):
re.compile(r'^([0-9]{1,3}\.){3}[0-9]{1,3}(/(16|24))')
它匹配CIDR块/ 16或/ 24,但不再匹配IP地址(例如,192.168.0.1)。
不是'?'应该检查一个组是否有可选的发生?我做错了什么?
注意:我知道IP地址正则表达式本身并不完美,但我更感兴趣的是获得有关所述问题的帮助。
答案 0 :(得分:7)
这应该有效:
^([0-9]{1,3}\.){3}[0-9]{1,3}($|/(16|24))$
它会检查$
(行结束)或/
以及16
或24
。
就像你说?
标记一个组是可选的,这意味着如果可能的话,它会尝试在匹配中包含它。但在某些情况下,它不能像192.168.0.0/aaaa
那样,但因为它是可选的,它仍然会匹配其他部分。
这就是为什么上述正则表达式更适合您的需求。这样,只有在/24
,/16
或行尾结束时才能获得匹配项。 192.168.0.1
。
答案 1 :(得分:2)
匹配0.0.0.0
到255.255.255.255
。如果指定了CIDR块,则仅在CIDR为16
或24
时才匹配。的 In action 强>:
^ # Start string
(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\. # A in A.B.C.D
(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\. # B in A.B.C.D
(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\. # C in A.B.C.D
(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)($|/(16|24))? # D in A.B.C.D and /16 or /24
$ # End string
答案 2 :(得分:0)
'?'的语义有点复杂(只是一点点)。你可以把它想象成副词“可能”的同义词 它以这种方式工作:如果有一个子串匹配我的模式那么继续匹配过程。我“突出”了IF和那么,因为暗示的语义说,如果前提不满意,整个句子仍然是真的。
因此,我们现在将此原则应用于您的案例。你放了'?'在后缀上。让我们假设前一部分匹配,现在让我们处理后缀:如果有一个与你的模式匹配的后缀,整个字符串将匹配。如果后缀不匹配,则没有问题:标有“?”的块是“可选的”(记住“可能”的语义或等效的蕴涵语义),因此字符串仍然匹配。
因此,放一个'?'模式的最后一部分中的块不是很有用,因为字符串仍然匹配,无论是否有匹配的后缀。实际上,可选块仅在字符串的中间有用。
答案 3 :(得分:0)
是否有一些理由让你觉得有必要用一个正则表达式来解决这个问题?它真的是钉子(*)吗?是否有一些原因导致您无法安装和使用Python IPAddr模块并使用它来解析和操作您的IP地址?我猜你可以这样做:
#!/usr/bin/env python
import ipaddr
...
mynet = ipaddr.IPv4Network('192.168.0.0/16')
try:
other = ipaddr.IPv4Network(other_network_string)
nm = other.netmask
except ipaddr.AddressValueError:
other = None
nm = None
...
if nm and nm == mynet.netnmask:
be_happy()
换句话说,有一个软件包,其中有人完成了解析和操作IP地址字符串的所有繁重工作。你真的想要为你的代码重做多少?你想花多少时间测试你的新代码并找到这个包的创建者可能找到和修复的相同类型的错误?
如果我听起来像是在抨击这一点......这是因为这种方法看起来与使用正则表达式解析HTML(或XML)的尝试完全相似,而不是使用现有的,经过测试的,强大的解析器写了。