Python正则表达式,不包括多个换行符

Python正则表达式,不包括多个换行符,python,regex,regex-negation,Python,Regex,Regex Negation,所以我在解析文本时遇到了一个问题。我试图解析音乐文件,它们是半格式化的。例如,我试图从歌词中排除合唱。大多数情况下,格式如下所示: [Chorus: x2] Some Lyrics Some More Lyrics [Verse] Lyrics Lyrics 然而,有时合唱是文件的最后一部分: Lyrics [Chorus] Some Lyrics Other Lyrics 它将起作用;但是,对于其他文件中最后的合唱部分不在末尾,它将删除需要保留的诗句。所有带诗句的合唱乐段之间至少有两行新行

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

[Chorus: x2] Some Lyrics Some More Lyrics [Verse] Lyrics Lyrics 然而,有时合唱是文件的最后一部分:

Lyrics [Chorus] Some Lyrics Other Lyrics 它将起作用;但是,对于其他文件中最后的合唱部分不在末尾,它将删除需要保留的诗句。所有带诗句的合唱乐段之间至少有两行新行。所以我提出了这个解决方案:

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

但它不起作用。有人能给我解释一下使上述语句起作用的正确正则表达式吗?或者是一种更好的方法,只删除文本部分末尾的合唱块,这样也可以保留最后合唱不在末尾的文件。

我宁愿一行一行地跳过歌词,而不是使用正则表达式,并决定是否使用基本上是蹩脚的有限状态机来保持每一行:

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.*?\].*?(\n{2,}|$)

它只匹配结尾处的
chorus
块。不要忘记在这两个正则表达式中启用DOTALL修饰符

尝试所有类型的合唱。替换为
空字符串
。请参阅演示


所以你只想删除作为结尾的部分,而保留在一首诗之前的部分?实际上,我将几个合唱正则表达式替换与无数其他表达结合起来,以过滤文本中的其他细微差别。文本档案的格式不尽相同,所以我目前有大约8个Chorus文本regex替换。但是在这个特殊的例子中,是的,我想要一个函数,如果它在结尾,就删除它,否则就保留它(标记通常不说韵文,并且通常不在[]delimeters中,但是合唱标记应该在一个[chrus.*?]标记中)@andoni您期望的输出是什么?您的意思是
\[Chorus.*.\].*(\n{2,}124$)
@AvinashRaj这正是我想要的!非常感谢你。我甚至没有想到将它们与交替组合,这样我就不会有无结尾合唱块的问题!这对于大多数格式化来说都是非常有效的。有些文件的格式是使用合唱标记,然后在诗句开始前只有两行换行符,没有每个句子的诗句标记(这就是为什么我在问题中包括subChorus2,以了解如何处理其他格式)。嗯,我可以修改一下这个来处理那些边缘案例。另外,您知道逐行执行与正则表达式相比的性能吗?我正在用超过2000万行的歌词来运行它。@andoni我怀疑你将主要受到磁盘读写速度的限制。这里的操作(检查一个字符串是否是另一个字符串中的
)相当快,假设您的行不是很长。我最初想要一个不依赖于开头的\n\n的解决方案。你对这个问题的评论提供了最理想的答案,我认为你应该得到公认的答案。经过进一步思考,我相信在所有格式中,开头的\n\n也足够了。谢谢,不客气<代码>(?!.*\n\n)
在开始处声明匹配不会包含任何空行。
Lyrics

------------
[Verse]
Lyrics
Lyrics
\[Chorus.*?\].*?(\n{2,}|$)
(?!.*\n\n)\[Chorus.*?\].*?$
\[Chorus:[^\]]+\][\s\S]*?(?=\n{2}|$)