我尝试使用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')]
答案 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]?)
使用非捕获组:
(?:(?: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]?)
正如你所看到的那样,当你起诉非捕获组时,你没有任何组,整个正则表达式将解释为一组通常是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')]