IPv4匹配的正则表达式

时间:2015-07-04 13:59:45

标签: python regex

我尝试使用regex匹配IPv4地址。我得到了regex

但我无法理解其中的?:

## r'(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'

>>> import re
>>> re.findall(r'(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)', txt)
['254.123.11.13', '254.123.11.14', '254.123.12.13', '254.123.12.14', '254.124.11.13', '254.124.11.14', '254.124.12.13']

我知道?:是为了避免捕获一个群体,但在这里我无法理解它。

更新 如果我删除?:,我会得到以下结果。我以为我会在元组中获取IP地址以及捕获的组。

>>> re.findall(r'((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)', txt)
[('11.', '11', '13'), ('11.', '11', '14'), ('12.', '12', '13'), ('12.', '12', '14'), ('11.', '11', '13'), ('11.', '11', '14'), ('12.', '12', '13')]

2 个答案:

答案 0 :(得分:1)

正如我在评论中所说,如果你不使用非捕获组而不是匹配你的整个正则表达式,并且由于这个说明你在你的正则表达式中有3个组你将得到3个结果每个IP。

为了更好地演示,请参阅以下状态机:

没有非捕获组:

((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)

Regular expression visualization

Debuggex Demo

使用非捕获组:

(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)

Regular expression visualization

Debuggex Demo

正如你所看到的那样,当你起诉非捕获组时,你没有任何组,整个正则表达式将解释为一组通常是0组!

答案 1 :(得分:1)

在这种情况下需要非捕获组,因为IPv4四重奏的{3}重复说明符仅返回第三个匹配项。然而,外部组将提供所有3个匹配的内部匹配:(q {3})其中q =正则表达式,用于四重奏中的数字。但是我们想隐藏第三个匹配内部组的非捕获说明符。

请参阅下面的正则表达式,没有非捕获,问题和解决方案。

q = r'(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'

在没有非捕获的情况下重现{3}重复问题:

t = '(%s\.){3}%s' % (q,q)
>>> re.findall(t,txt)
[('11.', '11', '13'), ('11.', '11', '14')]

解决方案,如果您想要单独捕获元组:

s='{0}\.{0}\.{0}\.{0}'.format(q)
>>> re.findall(s, txt)
[('254', '123', '11', '13'), ('254', '123', '11', '14')]

s='({0}\.{0}\.{0}\.{0})'.format(q)
>>> re.findall(s,txt)
[('254.123.11.13', '254', '123', '11', '13'), ('254.123.11.14', '254', '123', '11', '14')]