我是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
答案 0 :(得分:1)
尝试以下Demo:
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 ",
'...'
]
}
为了进一步详细说明模式,它使用命名组将三个不同的组分开。使用[^\]+]
和类似方法意味着找到所有不是 ]
(同样,当\)
意味着所有 not {{1 }})。在歌词部分,我们排除以)
和[
开头的任何内容。 link to the demo on regex101将在需要时更详细地解释这些组件。
如果您不喜欢主歌词中的换行符,请使用(
(不包括(?P<Lyrics>[^\[\(\n]+)
)来使歌词不换行:
\n
答案 1 :(得分:1)
您可以使用正则表达式组在右括号和右括号之间搜索文本。如果您的正则表达式中有一个组(圆括号内的子模式),则re.findall将仅返回这些括号的内容。
例如,"\[(.*?)\]"
只会找到部分标签,不包括方括号(因为它们不在组中)。
正则表达式"\)(.*?)\("
仅找到最后一行(“幻影”中的“ \ nNightcrawlin'”)。
同样,我们可以在第一行找到"\](.*?)\["
。
将两种类型的方括号组合到一个字符类中,(看起来更加凌乱)正则表达式"[\]\)](.*?)[\[\(]"
捕获了所有歌词。
它将错过在其之前或之后没有方括号的行(即,如果有,则在[简介]之前的最开始;如果其后没有支持人声,则在末尾)。可能的解决方法是在字符串的末尾添加“]”字符,并在末尾添加“ [”字符,以强制匹配在字符串的末尾开始/结束。请注意,我们需要添加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)