簡體   English   中英

如何將正則表達式與多個重疊模式匹配?

[英]How to match regex with multiple overlapping patterns?

上下文

我有一個由混合 mp3 信息組成的字符串,我必須嘗試匹配由任意字符串和標記組成的模式。 它是這樣工作的:

  1. 該程序向用戶顯示給定的字符串

The Beatles_Abbey_Road-SomeWord-1969

  1. 用戶輸入一個模式來幫助程序解析字符串

%Artist_%Album-SomeWord-%Year

  1. 然后我想顯示比賽的結果(但需要你的幫助)

找到 2 個可能的匹配項:
[1] {'藝術家':'披頭士','專輯':'Abbey_Road','年份':1969}
[2] {'藝術家':'Beatles_Abbey','專輯':'Road','Year':1969}

問題

例如,假設模式是藝術家姓名后跟標題(分隔符:'-')。

示例 1:

>>> artist = 'Bob Marley'
>>> title = 'Concrete Jungle'
>>> re.findall(r'(.+)-(.+)', '%s-%s' % (artist,title))
[('Bob Marley', 'Concrete Jungle')]

到目前為止,一切都很好。 但...
我無法控制使用的分隔符,也無法保證它不存在於標簽中,因此存在更棘手的情況:

示例 2:

>>> artist = 'Bob-Marley'
>>> title = 'Roots-Rock-Reggae'
>>> re.findall(r'(.+)-(.+)', '%s-%s' % (artist,title))
[('Bob-Marley-Roots-Rock', 'Reggae')]

正如預期的那樣,它在這種情況下不起作用

如何生成藝術家/標題的所有可能組合?

[('Bob', 'Marley-Roots-Rock-Reggae'),
 ('Bob-Marley', 'Roots-Rock-Reggae')
 ('Bob-Marley-Roots', 'Rock-Reggae'),
 ('Bob-Marley-Roots-Rock', 'Reggae')]

正則表達式是用於該工作的工具嗎?

請記住,要匹配的標簽數量和這些標簽之間的分隔符不是固定的,而是用戶定義的(因此要使用的正則表達式必須是可動態構建的)。
我嘗試嘗試貪婪與最小匹配前瞻斷言,但沒有成功。

謝謝你的幫助

這個解決方案似乎有效。 除了正則表達式之外,您還需要一個元組列表來描述模式,其中每個元素對應於正則表達式的一個捕獲組。

對於披頭士樂隊的例子,它看起來像這樣:

pattern = r"the (.+_.+)-SomeWord-(.+)"
groups = [(("Artist", "Album"), "_"), ("Year", None)]

因為ArtistAlbum僅由一個分隔符分割,所以它們將被一起捕獲在一個組中。 列表中的第一項表示第一個捕獲組將被拆分為和Artist和一個Album ,並將使用_作為分隔符。 列表中的第二項表示第二個捕獲組將直接用作Year ,因為元組中的第二個元素是None 然后您可以像這樣調用 function:

>>> get_mp3_info(groups, pattern, "the Beatles_Abbey_Road-SomeWord-1969")
[{'Album': 'Abbey_Road', 'Year': '1969', 'Artist': 'Beatles'}, {'Album': 'Road', 'Year': '1969', 'Artist': 'Beatles_Abbey'}]

這是代碼:

import re
from itertools import combinations

def get_mp3_info(groups, pattern, title):
    match = re.match(pattern, title)
    if not match:
        return []
    result = [{}]
    for i, v in enumerate(groups):
        if v[1] is None:
            for r in result:
                r[v[0]] = match.group(i+1)
        else:
            splits = match.group(i+1).split(v[1])
            before = [d.copy() for d in result]
            for comb in combinations(range(1, len(splits)), len(v[0])-1):
                temp = [d.copy() for d in before]
                comb = (None,) + comb + (None,)
                for j, split in enumerate(zip(comb, comb[1:])):
                    for t in temp:
                        t[v[0][j]] = v[1].join(splits[split[0]:split[1]])

                if v[0][0] in result[0]:
                    result.extend(temp)
                else:
                    result = temp
    return result

鮑勃馬利的另一個例子:

>>> pprint.pprint(get_mp3_info([(("Artist", "Title"), "-")],
...               r"(.+-.+)", "Bob-Marley-Roots-Rock-Reggae"))
[{'Artist': 'Bob', 'Title': 'Marley-Roots-Rock-Reggae'},
 {'Artist': 'Bob-Marley', 'Title': 'Roots-Rock-Reggae'},
 {'Artist': 'Bob-Marley-Roots', 'Title': 'Rock-Reggae'},
 {'Artist': 'Bob-Marley-Roots-Rock', 'Title': 'Reggae'}]

像這樣的東西而不是使用正則表達式呢?

import re

string = "Bob-Marley-Roots-Rock-Reggae"

def allSplits(string, sep):
    results = []
    chunks = string.split('-')
    for i in xrange(len(chunks)-1):
        results.append((
            sep.join(chunks[0:i+1]),
            sep.join(chunks[i+1:len(chunks)])
        ))

    return results

print allSplits(string, '-')
[('Bob', 'Marley-Roots-Rock-Reggae'),
 ('Bob-Marley', 'Roots-Rock-Reggae'),
 ('Bob-Marley-Roots', 'Rock-Reggae'),
 ('Bob-Marley-Roots-Rock', 'Reggae')]

暫無
暫無

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

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