正则表达式:为什么在re.findall()中包含空字符串(在元组列表中)?

时间:2015-06-11 21:40:02

标签: python regex

根据模式匹配here,匹配为213.239.250.131014.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地址?

2 个答案:

答案 0 :(得分:7)

每当使用capturing group时,它总是返回一个子匹配,即使它是空/ null。您有3个捕获组,因此您将始终在findall结果中使用它们。

在regex101.com中,您可以在选项中打开这些非参与组:

enter image description here

您可以通过删除捕获组来收紧正则表达式:

(?:[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))

online Python demo的输出:

['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})

以简单的方式说出每个圆括号定义一个捕获组,如果值匹配则显示该捕获组。