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

问题描述 投票:1回答:3

我对更高级的正则表达式概念更新,并开始研究后面的观察和前瞻,但我感到困惑,需要一些指导。我有一个场景,我可能有几种不同类型的发布拉链,名称如下:

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

或者如果第二个zip匹配组:

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

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

python regex lookahead lookbehind lookaround
3个回答
1
投票

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

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

这样就产生了三组:第一组是版本,第二组是可选的:短划线-后跟字母字符,然后是可选的点序列,后跟数字,最后是.zip

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

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

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

((?:\.\d+)*):一个又有这样的\.\d+非捕获子组的组,所以我们捕获一个点后跟一个数字序列,这个模式重复零次或多次。

例如:

rgx = re.compile(r'(v\d+(?:\.\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', '', '')]

2
投票

你可以使用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.']]

2
投票

以下是我将如何使用re.search来解决这个问题。请注意,我们不需要这里的外观;只是一个相当复杂的模式才能完成这项任务。

import re

regex = r"(v\d+(?:\.\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

Demo

如果你没有大量的正则表达式经验,提供每个步骤的解释可能不会让你加快速度。不过,我会评论一些括号中使用的?:。在这种情况下,?:告诉正则表达式引擎不要捕获内部的内容。我们这样做是因为你只想捕获(最多)三个特定的东西。

© www.soinside.com 2019 - 2024. All rights reserved.