3

我需要检查任何 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 地址正则表达式本身并不完美,但我更感兴趣的是在所描述的问题上获得帮助。

4

4 回答 4

12

这应该有效:

^([0-9]{1,3}\.){3}[0-9]{1,3}($|/(16|24))$

它检查$( line end ) or/16or 24

就像您所说?的将组标记为可选,这意味着它会尽可能尝试将其包含在匹配中。但是在某些情况下它不能像 in 一样192.168.0.0/aaaa,但是因为它是可选的,它仍然会匹配其他部分。

这就是为什么上述正则表达式更适合您的需求。这样你只会得到一个匹配,如果它以/24,/16行尾结尾,例如。192.168.0.1.

于 2012-08-27T11:42:50.427 回答
3

准确匹配

匹配0.0.0.0通过255.255.255.255. 如果指定了 CIDR 块,则仅当 CIDR 为16或时才匹配24在行动

^                                                 # 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
于 2012-08-27T13:29:12.867 回答
1

有什么理由让你觉得有必要用一个正则表达式来解决这个问题吗?真的是钉子(*)吗?您是否有某些原因无法安装和使用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)过于相似,而不是使用已经编写的现有的、经过测试的、健壮的解析器。

  • (如果手头唯一的工具是锤子,那么每个问题看起来都像钉子)
于 2012-08-27T12:11:35.293 回答
0

'?' 的语义 有点复杂(只是有点)。你可以把它想象成副词“可能”的同义词。
它是这样工作的:如果有一个匹配我的模式的子字符串,那么继续匹配过程。我“突出显示”了 IF 和 THEN,因为含义的语义表明,如果不满足前提,则整个句子仍然正确。

因此,现在让我们将此原则应用于您的案例。你放了一个'?在一个后缀上。让我们假设前一部分匹配,现在让我们处理后缀:如果有一个后缀与您的模式匹配,则整个字符串将匹配。如果后缀不匹配,则没有问题:标有'?'的块 是“可选的”(记住“可能”语义,或者等效地,隐含语义),因此字符串仍然匹配。

因此,放一个“?” 模式最后一部分的块不是很有用,因为字符串仍然会匹配,无论是否有匹配的后缀。实际上,可选块仅在字符串中间有用。

于 2012-08-27T11:54:00.560 回答