如何匹配具有多个重叠模式的正则表达式?

2024-06-01 04:17:44 发布

您现在位置:Python中文网/ 问答频道 /正文

上下文

我有一个由混合mp3信息组成的字符串,我必须尝试与由任意字符串和令牌组成的模式进行匹配。它是这样工作的:

  1. 程序向用户显示给定的字符串

the Beatles_Abbey_Road-SomeWord-1969

  1. 用户输入一个模式来帮助程序解析字符串

the %Artist_%Album-SomeWord-%Year

  1. 然后我想展示比赛结果(但需要你的帮助)

2 possible matches found :
[1] {'Artist': 'Beatles', 'Album':'Abbey_Road', 'Year':1969}
[2] {'Artist': 'Beatles_Abbey', 'Album':'Road', 'Year':1969}

问题

作为一个例子,假设pattern是艺术家姓名后跟标题(分隔符:'-')。在

例1:

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

到目前为止,还不错。但是…
我无法控制所使用的分隔符,也无法保证它不在标记中,因此存在更棘手的情况:

例2:

^{pr2}$

正如预期的那样,在这种情况下,它不起作用。在

如何生成所有可能的艺术家/头衔组合?

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

regex是用于该工作的工具吗?在

请记住,要匹配的标记数和这些标记之间的分隔符不是固定的,而是用户定义的(因此要使用的正则表达式必须是动态构建的)。
我试着用贪婪与最小匹配的断言进行实验,但没有成功。在

谢谢你的帮助


Tags: 字符串用户标记albumartistyearbob分隔符
2条回答

这个解决方案似乎有效。除了正则表达式之外,还需要一个元组列表来描述模式,其中每个元素对应于正则表达式的一个捕获组。在

以披头士乐队为例,应该是这样的:

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

因为Artist和{}只由一个分隔符拆分,所以它们将被捕获到一个组中。列表中的第一项指示第一个捕获组将被拆分为和ArtistAlbum,并将使用_作为分隔符。列表中的第二项指示第二个捕获组将直接用作Year,因为元组中的第二个元素是None。然后可以像这样调用函数:

^{pr2}$

代码如下:

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

另一个例子是Bob Marley:

>>> 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, '-')
^{pr2}$

相关问题 更多 >