为了账号安全,请及时绑定邮箱和手机立即绑定

Python RE。排除部分结果

Python RE。排除部分结果

qq_花开花谢_0 2021-11-16 16:26:15
我是 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 refile = '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 = versesexclude.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
查看完整描述

2 回答

?
明月笑刀无情

TA贡献1828条经验 获得超4个赞

试试这个演示:


pattern = r'(?P<Verse>\[[^\]]+])|(?P<Backing>\([^\)]+\))|(?P<Lyrics>[^\[\(]+)'

您可以使用re.finditer来隔离组。


breakdown = {k: [] for k in ('Verse', 'Backing', 'Lyrics')}

for p in pattern.finditer(song):

    for key, item in p.groupdict().items():

        if item: breakdown[key].append(item)

结果:


{

  'Verse': 

    [

      '[Intro]', 

      '[Chorus: Travis Scott]'

    ], 

  'Backing': 

    [

      '(Freeze)', 

      '(Skrrt, Skrrt)'

    ], 

  'Lyrics': 

    [

      '\nD.A. got that dope!\n\n', 

      '\nIce water, turned Atlantic ', 

      "\nNightcrawlin' in the Phantom ", 

      '...'

    ]

}

为了进一步详细说明该模式,它使用命名组来分隔三个不同的组。使用[^\]+]和相似只是意味着找到所有不是的 ](同样 when\)意味着一切都不是 ))。在歌词部分,我们排除了以[和开头的任何内容(。在对regex101演示链接可以解释组件的详细信息,如果您需要。


如果您不关心主歌词中的换行符,请使用(?P<Lyrics>[^\[\(\n]+)(不包括\n)将您的歌词转换为没有换行符:


'Lyrics': [

  'D.A. got that dope!', 

  'Ice water, turned Atlantic ',

  "Nightcrawlin' in the Phantom ", 

  '...'

]


查看完整回答
反对 回复 2021-11-16
?
慕斯王

TA贡献1864条经验 获得超2个赞

您可以使用正则表达式组搜索封闭括号和开放括号之间的文本。如果您的正则表达式中有一个组(圆括号内的子模式),则 re.findall 将只返回这些括号的内容。


例如,"\[(.*?)\]"会发现您只是部分标签,不包括方括号(因为它们在组之外)。


正则表达式"\)(.*?)\("只会找到最后一行(“\nNightcrawlin' in the Phantom”)。

同样,我们可以找到第一行"\](.*?)\["。


将两种类型的括号组合成一个字符类,(看起来非常混乱)正则表达式"[\]\)](.*?)[\[\(]"捕获所有歌词。


它会错过之前或之后没有括号的行(即,如果有的话,在 [Intro] 之前的开头,或者如果之后没有和声的话,则在结尾处)。一种可能的解决方法是在字符串末尾添加“]”字符并将“[”字符附加到末尾以强制匹配开始/结束。请注意,我们需要添加 DOTALL 选项以确保通配符“。” 将匹配换行符 "\n"


import re


lyrics = """[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)


查看完整回答
反对 回复 2021-11-16
  • 2 回答
  • 0 关注
  • 327 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信