Python 正则表达式查找连字符后非数字范围的匹配组,如果范围不存在,则忽略模式的其余部分



我对更高级的正则表达式概念较新,并开始研究后视和展望,但我感到困惑,需要一些指导。我有一个场景,其中我可能有几种不同类型的发布压缩文件,名称如下:

v1.1.2-beta.2.zip
v1.1.2.zip

我想写一个单行正则表达式,可以在两种类型中找到匹配组。例如,如果文件类型是第一个zip,我想要三个匹配组,如下所示:

v1.1.2-beta.2.zip
Group 1: v1.1.2
Group 2: beta
Group 3. 2

或者,如果第二个压缩一匹配组:

v1.1.2.zip
Group 1: v1.1.2

这就是事情开始让我感到困惑的地方,因为我假设正则表达式需要断言连字符是否存在,如果不存在,则只查找一个匹配组,如果没有找到其他 3 个。

(v[0-9.]{0,}).([A-Za-z]{0,}).([0-9]).zip

这是我编写的初始正则表达式,女巫成功匹配了第一种类型,但没有条件。我正在考虑做一些类似匹配连字符后非数字的组范围的事情,但无法完全让它工作,并且不知道让它忽略模式的其余部分,如果找不到连字符,则只接受第一组

([D]{0,}(?=[-]) # Does not work

有人可以指出我正确的方向吗?

您可以使用re.findall

import re
s = ['v1.1.2-beta.2.zip', 'v1.1.2.zip']
final_results = [re.findall('[a-zA-Z]{1}[d.]+|(?<=-)[a-zA-Z]+|d+(?=.zip)', i) for i in s]
groupings = ["{}n{}".format(a, 'n'.join(f'Group {i}: {c}' for i, c in enumerate(b, 1))) for a, b in zip(s, final_results)]
for i in groupings:
print(i)
print('-'*10)

输出:

v1.1.2-beta.2.zip
Group 1: v1.1.2
Group 2: beta
Group 3: 2
----------
v1.1.2.zip
Group 1: v1.1.2.
----------

请注意,从re.findall获得的结果是:

[['v1.1.2', 'beta', '2'], ['v1.1.2.']]

以下是我如何使用re.search来处理这个问题。 请注意,我们在这里不需要环顾四周;只需一个相当复杂的模式即可完成这项工作。

import re
regex = r"(vd+(?:.d+)*)(?:-(w+).(d+))?.zip"
str1 = "v1.1.2-beta.2.zip"
str2 = "v1.1.2.zip"
match = re.search(regex, str1)
print(match.group(1))
print(match.group(2))
print(match.group(3))
print("n")
match = re.search(regex, str2)
print(match.group(1))
v1.1.2
beta
2
v1.1.2

演示

如果您没有大量的正则表达式经验,那么提供每个步骤的解释可能不会让您跟上进度。 不过,我将就一些括号中出现的?:的使用发表评论。 在这种情况下,?:告诉正则表达式引擎不要捕获里面的内容。 我们这样做是因为您只想捕获(最多(三个特定内容。

我们可以使用以下正则表达式:

(vd+(?:.d+)*)(?:[-]([A-Za-z]+))?((?:.d+)*).zip

因此,这会产生三组:第一组是版本,第二组是可选的:破折号-后跟字母字符,然后是可选的点序列,后跟数字,最后是.zip

如果我们忽略.zip后缀(好吧,我认为这是相当微不足道的(,那么仍然有三组:

(vd+(?:.d+)*):以v开头,后跟d+(一个或多个数字(的正则表达式组。然后我们有一个非捕获组(以(?:..)开头的组,它捕获.d+点后跟一个或多个数字序列。我们重复这样的子组零次或多次。

(?:[-]([A-Za-z]+))?:以连字符[-]开头,然后是一个或多个[A-Za-z]字符的捕获组。但是,捕获组是可选的(末尾的?(。

((?:.d+)*):一个再次具有这种非捕获子组.d+组,因此我们捕获一个点,后跟一系列数字,并且此模式重复零次或多次。

例如:

rgx = re.compile(r'(vd+(?:.d+)*)([-][A-Za-z]+)?((?:.d+)*).zip')

然后我们得到:

>>> rgx.findall('v1.1.2-beta.2.zip')
[('v1.1.2', '-beta', '.2')]
>>> rgx.findall('v1.1.2.zip')
[('v1.1.2', '', '')]

相关内容

最新更新