Skip to main content
 首页 » 编程设计

python之匹配和弦的正则表达式,带有民族口音的问题

2025年05月04日27yyy_WW

我正在处理这个问题。我有包含数十首歌曲的 *.txt 文件。每首歌可能包括

  • 姓名
  • 带和弦的线条
  • 有歌词的台词
  • 空行

我正在编写 Python 脚本,它逐行读取文件。我需要用和弦识别线条。为此,我决定使用正则表达式,因为它看起来很有趣,但对于此类任务来说是一个强大的工具。我是正则表达式的新手,我已经做到了 tutorial (我很喜欢)。我写过这样的东西

\b ?\(?([AC-Hac-h]{1})(#|##|b|bb)?(is|mi|maj|sus)?\d?[ \n(/\(\))?] 

我对此不是很满意,因为它不能正常工作。问题之一是歌曲的语言使用了很多口音。第二个:和弦可能成对出现——例如C(D),他/她。可以看我的做法here .

注意 为了提高最终脚本的可读性,我会将正则表达式拆分为更多变量,然后将它们加在一起。

编辑

在重读我的问题后,我认为我的目标可能不够明确。例如,我想要很多不同类型的和弦:

C, C#, Cis, c#, Cmaj, Cmi, Csus, C7, C#7, Db, Dbsus 

有时可能会有(不超过两个)和弦彼此相邻,例如:C7/D7, Cmi(a)。最好的解决方案是将这些“对”放在一起匹配 C7/D7 而不是 C7 和 D7。我认为,有了这个附加条件,它可能会有点健壮,但如果它不必要地困难,我可能会选择(我假设)更简单的版本(意思是:匹配 C7 和 D7 而不是 C7/D7),稍后单独处理。

请您参考如下方法:

您的 Python 脚本逐行读取文本文件,您希望使用正则表达式找出当前行是否包含和弦或其他信息。

也许在每一行上应用正则表达式 ^[\t #()/\dAC-Hac-jmsu]+$ 就足够了。如果正则表达式未返回匹配项,则该行包含不允许出现在带有和弦的行中的字符。也许这个仅使用单个字符类定义的简单正则表达式就足够了。

但也可能带有名称或歌词的行也与上面的表达式匹配。对于您的示例,情况并非如此,但也可能如此。在这种情况下,我建议首先在每一行上使用函数 strip() 来删除每一行开头和结尾的空格和制表符。然后应用以下正则表达式

^(?:[#()/\dAC-Hac-jmsu]{1,6}[\t ]+?)*[#()/\dAC-Hac-jmsu]{1, 6}$

不同之处在于,现在每个不包含空格或制表符的字符串的长度都必须在 1 到 6 之间。不允许使用更长的字符串。有了这个额外的规则,就可以不再检测带有和弦的线条时出现误报。

和弦线检测规则的问题肯定是字母作为名称或仅由和弦允许的字母组成的歌词文本也可以匹配。一种解决方案是创建一个字符串列表,该列表仅包含允许用于和弦的字母,并在 OR 表达式中使用它们。这将很可能避免由名称或歌词字符串引起的误报。使用完整的和弦列表,很可能还可以定义更短的规则,而无需在 OR 表达式中列出所有和弦。