Python正则表达式排除多个换行符

时间:2014-12-24 01:25:39

标签: python regex regex-negation

所以我在解析文本时遇到了问题。我试图解析音乐文件,它们是半格式化的。例如,我试图从歌词中排除合唱。大多数情况下,格式如下:

[Chorus: x2]
Some Lyrics
Some More Lyrics

[Verse]
Lyrics
Lyrics

在这种情况下,这两个函数可以正确解析:

subChorus = re.sub(r'\[Chorus.*?\].*?\[', '[', lyrics, flags = re.DOTALL);
subChorus2 = re.sub(r'\[Chorus.*?\].*?(\n{2,})', '', lyrics, flags = re.DOTALL);

但是,偶尔合唱是文件的最后一部分:

Lyrics

[Chorus]
Some Lyrics
Other Lyrics

在这种情况下,我无法找出正确的表达方式来删除合唱。如果我只是做

subChorusEnd = re.sub(r'\[Chorus.*?\].*?$', '', lyrics, flags = re.DOTALL);

它会起作用;但是,对于最终合唱部分不在最后的其他文件,它将删除需要保留的经文。所有带有以下经文的合唱块都至少由两个换行符分隔。所以我提出了这个解决方案:

subChorusEnd = re.sub(r'\[Chorus.*?\][^(\n{2,})]*?$', '', subChorus4, flags = re.DOTALL);

但它不起作用。有人可以向我解释正确的正则表达式,以使上述语句工作或更好的方法,只删除位于文本部分末尾的合唱块,这也将保留最终合唱不在最后的文件

3 个答案:

答案 0 :(得分:1)

您可以尝试使用以下正则表达式匹配所有Chorus块。

\[Chorus.*?\].*?(\n{2,}|$)

DEMO

OR

(?!.*\n\n)\[Chorus.*?\].*?$

它仅匹配最后的chorus块。不要忘记在两个正则表达式中启用DOTALL修饰符。

DEMO

答案 1 :(得分:0)

我不想使用正则表达式,而是逐行逐步翻阅歌词,并决定是否使用基本上是一个糟糕的有限状态机来保持每一行:

lyrics1 = '''Lyrics

[Chorus]
Some Lyrics
Other Lyrics'''

lyrics2 = '''[Chorus: x2]
Some Lyrics
Some More Lyrics

[Verse]
Lyrics
Lyrics'''

def clean(lyrics):
    result = []
    omitting = False
    for line in lyrics.split('\n'):
        if '[Chorus' in line:
            omitting = True
        if '[' in line and '[Chorus' not in line:
            omitting = False
        if not omitting:
            result.append(line)
    return '\n'.join(result)

print(clean(lyrics1))
print('------------')
print(clean(lyrics2))

结果:

Lyrics

------------
[Verse]
Lyrics
Lyrics

所以基本上,如果我们看到" Chorus"线和停止输出线;然后,如果我们看到任何括号内的东西不是" Chorus",我们将旗帜翻转并恢复输出线。

我不知道您正在解析的实际文件是什么样的,但是这样的策略可能比投入庞大的正则数据更有效。

答案 2 :(得分:0)

\[Chorus:[^\]]+\][\s\S]*?(?=\n{2}|$)

尝试使用empty string所有类型的合唱。请参阅演示。

https://regex101.com/r/vN3sH3/77