根据模式匹配here,匹配为213.239.250.131
和014.10.26.06
。
然而,当我运行生成的Python代码并打印出re.findall(p, test_str)
的值时,我得到:
[('', '', '213.239.250.131'), ('', '', '014.10.26.06')]
我可以在列表中乱砍,它可以获取我正在寻找的值(IP地址),但是(i)它们可能并不总是处于元组中的相同位置,(ii)我和#39;我宁愿了解这里发生了什么,所以我可以收紧正则表达式,或者使用Python自己的re
功能只提取IP地址。
为什么我会得到这个元组列表,为什么明显的空白匹配,以及我们如何确保只返回IP地址?
答案 0 :(得分:7)
每当使用capturing group时,它总是返回一个子匹配,即使它是空/ null。您有3个捕获组,因此您将始终在findall
结果中使用它们。
在regex101.com中,您可以在选项中打开这些非参与组:
您可以通过删除捕获组来收紧正则表达式:
(?:[a-z0-9]{1,4}:+){3,5}[a-z0-9]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
甚至(?:[a-z0-9]{1,4}:+){3,5}[a-z0-9]{1,4}|\d{1,3}(?:\.\d{1,3}){3}
。
请参阅a regex demo
由于正则表达式模式不包含捕获组,re.findall
只会返回匹配,而不是捕获组内容:
import re
p = re.compile(r'(?:[a-z0-9]{1,4}:+){3,5}[a-z0-9]{1,4}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}')
test_str = "from mail.example.com (example.com. [213.239.250.131]) by\n mx.google.com with ESMTPS id xc4si15480310lbb.82.2014.10.26.06.16.58 for\n <alex@example.com> (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256\n bits=128/128); Sun, 26 Oct 2014 06:16:58 -0700 (PDT)"
print(re.findall(p, test_str))
['213.239.250.131', '014.10.26.06']
答案 1 :(得分:1)
这些是捕获组。 如果您这样做或查询,它将返回非匹配表达式的空匹配。
(([a-z0-9]{1,4}:+){3,5}[a-z0-9]{1,4})|(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})
第一组或有两组:
(([a-z0-9]{1,4}:+){3,5}[a-z0-9]{1,4})
之后或之后有第三个:
(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})
以简单的方式说出每个圆括号定义一个捕获组,如果值匹配则显示该捕获组。