Python RE。排除部分结果

我是 RE 的新手,我正在尝试提取歌词并分离出诗句标题、和声和主声:


下面是一些歌词的例子:


[Intro]

D.A. got that dope!


[Chorus: Travis Scott]

Ice water, turned Atlantic (Freeze)

Nightcrawlin' in the Phantom (Skrrt, Skrrt)...

经文标题包括方括号和它们之间的任何单词。他们可以成功地隔离


r'\[{1}.*?\]{1}'

和声与诗歌标题相似,但介于 () 之间。他们已通过以下方式成功隔离:


r'\({1}.*?\){1}'

对于主唱,我使用了


r'\S+'

这确实隔离了 main_vocals,但也隔离了诗句标题和和声。我不知道如何用简单的 RE 仅隔离主人声。


这是一个 python 脚本,它可以获得我想要的输出,但我想用 RE 来做(作为学习练习)并且无法通过文档弄清楚。


import re


file = 'D:/lyrics.txt'

with open(file, 'r') as f:

    lyrics = f.read()


def find_spans(pattern, string):

    pattern = re.compile(pattern)

    return [match.span() for match in pattern.finditer(string)]


verses = find_spans(r'\[{1}.*?\]{1}', lyrics)

backing_vocals = find_spans(r'\({1}.*?\){1}', lyrics)

main_vocals = find_spans(r'\S+', lyrics)


exclude = verses

exclude.extend(backing_vocals)


not_main_vocals = []

for span in exclude:

    start, stop = span

    not_main_vocals.extend(list(range(start, stop)))


main_vocals_temp = []

for span in main_vocals:

    append = True

    start, stop = span

    for i in range(start, stop):

        if i in not_main_vocals: 

            append = False

            continue

    if append == True: 

        main_vocals_temp.append(span)

main_vocals = main_vocals_temp


qq_花开花谢_0
浏览 328回答 2
2回答

明月笑刀无情

试试这个演示:pattern = r'(?P<Verse>\[[^\]]+])|(?P<Backing>\([^\)]+\))|(?P<Lyrics>[^\[\(]+)'您可以使用re.finditer来隔离组。breakdown = {k: [] for k in ('Verse', 'Backing', 'Lyrics')}for p in pattern.finditer(song):&nbsp; &nbsp; for key, item in p.groupdict().items():&nbsp; &nbsp; &nbsp; &nbsp; if item: breakdown[key].append(item)结果:{&nbsp; 'Verse':&nbsp;&nbsp; &nbsp; [&nbsp; &nbsp; &nbsp; '[Intro]',&nbsp;&nbsp; &nbsp; &nbsp; '[Chorus: Travis Scott]'&nbsp; &nbsp; ],&nbsp;&nbsp; 'Backing':&nbsp;&nbsp; &nbsp; [&nbsp; &nbsp; &nbsp; '(Freeze)',&nbsp;&nbsp; &nbsp; &nbsp; '(Skrrt, Skrrt)'&nbsp; &nbsp; ],&nbsp;&nbsp; 'Lyrics':&nbsp;&nbsp; &nbsp; [&nbsp; &nbsp; &nbsp; '\nD.A. got that dope!\n\n',&nbsp;&nbsp; &nbsp; &nbsp; '\nIce water, turned Atlantic ',&nbsp;&nbsp; &nbsp; &nbsp; "\nNightcrawlin' in the Phantom ",&nbsp;&nbsp; &nbsp; &nbsp; '...'&nbsp; &nbsp; ]}为了进一步详细说明该模式,它使用命名组来分隔三个不同的组。使用[^\]+]和相似只是意味着找到所有不是的 ](同样 when\)意味着一切都不是 ))。在歌词部分,我们排除了以[和开头的任何内容(。在对regex101演示链接可以解释组件的详细信息,如果您需要。如果您不关心主歌词中的换行符,请使用(?P<Lyrics>[^\[\(\n]+)(不包括\n)将您的歌词转换为没有换行符:'Lyrics': [&nbsp; 'D.A. got that dope!',&nbsp;&nbsp; 'Ice water, turned Atlantic ',&nbsp; "Nightcrawlin' in the Phantom ",&nbsp;&nbsp; '...']

慕斯王

您可以使用正则表达式组搜索封闭括号和开放括号之间的文本。如果您的正则表达式中有一个组(圆括号内的子模式),则 re.findall 将只返回这些括号的内容。例如,"\[(.*?)\]"会发现您只是部分标签,不包括方括号(因为它们在组之外)。正则表达式"\)(.*?)\("只会找到最后一行(“\nNightcrawlin' in the Phantom”)。同样,我们可以找到第一行"\](.*?)\["。将两种类型的括号组合成一个字符类,(看起来非常混乱)正则表达式"[\]\)](.*?)[\[\(]"捕获所有歌词。它会错过之前或之后没有括号的行(即,如果有的话,在 [Intro] 之前的开头,或者如果之后没有和声的话,则在结尾处)。一种可能的解决方法是在字符串末尾添加“]”字符并将“[”字符附加到末尾以强制匹配开始/结束。请注意,我们需要添加 DOTALL 选项以确保通配符“。” 将匹配换行符 "\n"import relyrics = """[Intro]D.A. got that dope![Chorus: Travis Scott]Ice water, turned Atlantic (Freeze)Nightcrawlin' in the Phantom (Skrrt, Skrrt)..."""matches = re.findall(r"[\]\)](.*?)[\[\(]", "]" + lyrics + "[", re.DOTALL)main_vocals = '\n'.join(matches)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python