簡體   English   中英

Python Regex在連字符后查找非數字范圍的匹配組,如果不存在范圍,則忽略其余模式

[英]Python Regex Find match group of range of non digits after hyphen and if range is not present ignore rest of pattern

我不熟悉更高級的正則表達式概念,並且開始研究背后的事和前瞻性,但是我感到困惑,需要一些指導。 我有一個場景,其中我可能有幾種不同類型的發布zip,它們的名稱如下:

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

在這里,事情開始讓我感到困惑,因為我認為正則表達式需要斷言是否存在連字符,如果不存在,則只尋找一個匹配組,否則就找不到另一個。

(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"(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

演示版

如果您對正則表達式沒有足夠的經驗,那么對每個步驟進行解釋很可能無法使您快速入門。 不過,我將對?:的使用發表評論,它出現在某些括號中。 在這種情況下, ?:告訴正則表達式引擎不要捕獲內部內容。 我們這樣做是因為您只想捕獲(最多)三個特定的事物。

我們可以使用以下正則表達式:

(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', '', '')]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM