正则表达式与和弦相匹配,与国家口音一致

时间:2014-05-11 15:23:07

标签: python regex

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

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

我正在编写Python脚本,它按行读取文件。我需要用和弦识别线条。为此我决定使用正则表达式,因为它看起来像是有趣但强大的工具来执行此类任务。我是regexp的新手,我已经完成了这个tutorial(我非常喜欢)。我写过类似的东西

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

我对此并不满意,因为它不能正常工作。其中一个问题是歌曲的语言使用了很多重音。第二个:和弦可能成对出现 - 例如C(D),h / e。您可以看到我的方法here

注意 为了在最终脚本中获得更好的可读性,我将regexp拆分为更多变量,然后将它们加在一起。

修改

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

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

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

1 个答案:

答案 0 :(得分:1)

您的Python脚本逐行读取文本文件,如果当前行是带有和弦或其他信息的行,您希望找到正则表达式。

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

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

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

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

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