【问题标题】:Regexp to match chords, issue with national accents正则表达式匹配和弦,国家口音问题
【发布时间】:2014-05-11 15:23:06
【问题描述】:

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

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

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

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

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

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

编辑

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

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

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

【问题讨论】:

  • 这个answer 可能会提供解决方案。
  • 不要在整个文件中使用正则表达式并希望它起作用,而是使用与弦线与歌词线分开的先验知识将线分类为和弦或非和弦。然后,一旦将它们分开,标记化就很容易了。
  • @roippi 结构与上面的列表项并不完全相同。当我说“可能”时,这意味着可能有几行例如只有歌词。所以,我不知道哪条线是哪条线。我的不好,我没有强调这一点。
  • 这并不能阻止您应用启发式方法来解决问题。你可以例如看看字母频率、字长、符号包含(带重音的行是歌词行)等。有很多方法可以做到。
  • @roippi 我已经考虑过了,但在我看来,这仍然是一种更困难的方法。我已经弄清楚如何更改编码,以便正则表达式正常工作。现在我将它写入文件时遇到问题(编码问题)。

标签: python regex


【解决方案1】:

您的 Python 脚本逐行读取文本文件,您想使用正则表达式找出当前行是带有和弦的行还是带有其他信息的行。

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2012-06-29
    • 2011-07-17
    • 1970-01-01
    • 2017-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多