【问题标题】:Regex for standard guitar lyric/chord bracketing标准吉他歌词/和弦包围的正则表达式
【发布时间】:2015-05-22 13:56:40
【问题描述】:

我正在尝试在为吉他/歌词格式化的标准文本文档中的和弦周围添加方括号,以使它们与 OnSong 应用程序更兼容。我有规则,但不明白如何匹配所有可能的组合。规则是:

  • 和弦将以单个大写字母 A-G 开头
  • 如果大写的 AG 后面跟着空格、换行符、#、b、m、sus、aug、dim、maj、min 或 / 我想读到下一个空格或换行符(因为标准吉他格式,像 F#min/E 这样的和弦是可能的,我不想费心把它全部拆开,我只想一直读到空格)
  • 如果大写字母 A-G 后跟另一个不在上述列表中的字母,则正则表达式不匹配(例如,名称“Ed”不匹配)
  • 如果由于“A”后面的单词不是有效的和弦,您可以弄清楚如何使“A small world”不匹配。
  • 如果替换可以在新括号之前(不开始一行时)和之后删除一个空格(以保持对齐),则超级加分 - 有人向我指出,这将在关闭和弦上失败......这是完全可以接受的。

几个注意事项:这是一个帮助脚本......不需要完美。我现在是手工做的,所以偶尔错过是可以的。我不是试图解析和弦的细节,只是将它们包装在 [] 中。虽然标准布局是 1 行和弦,1 行歌词,但这个不能指望,所以我知道有些场景偶尔会失败。

测试源(为了测试目的,和弦是随机的,以防任何音乐家要插话糟糕的音乐):

Db    Dsus4/F#           A            Cbmin/C
A man can't be asked for that much to do
D/F#        G         A           D#/E
And I can't sweep you off of your feet

应该变成:

[Db]  [Dsus4/F#]         [A]          [Cbmin/C]
A man can't be asked for that much to do
[D/F#]      [G]       [A]         [D#/E]
And I can't sweep you off of your feet

我的第一次尝试让我接近了:

([A-G]((?!\s).)*)

但是这也提取了以这些字母开头的单词。我现在转了一圈,只到了:

\b([CDEFGAB](#|##|b|bb|sus|maj|min|aug)?\b)

当我尝试使用 [^\s+] 时,我得到的结果好坏参半,我得到了更多我想要的东西,但也抛弃了我需要的东西。我想我只是在我的头上。任何帮助将不胜感激,任何关于它如何工作的解释都会更好。虽然我想要一个解决方案,但我也很想解释为什么它会起作用......

【问题讨论】:

  • 所以A# Eb // Oh man! 会变成[A#][Eb] // Oh man!?由于这些和弦的紧密性,我们松散了对齐(添加括号)。
  • 和弦相互对立的好点...有时对齐不起作用-我已经接受了这种命运:)
  • 您将通过什么语言或工具使用正则表达式?这是什么动物?
  • 没有考虑特定的语言...打算只制作一个小 shell 脚本或小型 Java 应用程序来处理文本文件。例如,这是吉他手/歌手获取歌曲的一种非常常见的格式。歌词上面有基本和弦的歌词。我还使用了一个可以读取文本文件的现场演奏应用程序,但是如果和弦被括号括起来,它会将它们转换为实际的和弦图,这非常有用。问题是,对于成千上万的歌曲文件,添加括号变得很麻烦。 (示例链接)tabs.ultimate-guitar.com/p/pearl_jam/alive_crd.htm

标签: regex guitar


【解决方案1】:

看看这个:

/([A-G](#|b)?)(\(?(M|maj|major|m|min|minor|dim|sus|dom|aug)?(\+|-|add)?\d*\)?)(\/([A-G](#|b)?))?/g

我是从chord-transposer

var XRegExp = require("xregexp");

// Chromatic scale starting from C using flats only.
var FLAT_SCALE = ["C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "Cb"];

// Chromatic scale starting from C using sharps only.
var SHARP_SCALE = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];

// Regex for recognizing chords
var ROOT_PATTERN = '(?<root>[A-G](#|b)?)';

var SUFFIX_PATTERN = '(?<suffix>\\(?(M|maj|major|m|min|minor|dim|sus|dom|aug)?(\\+|-|add)?\\d*\\)?)';

var BASS_PATTERN = '(\\/(?<bass>[A-G](#|b)?))?';

var MINOR_PATTERN = '(m|min|minor)+';

var CHORD_REGEX = XRegExp("^" + ROOT_PATTERN + SUFFIX_PATTERN + BASS_PATTERN + "$");

然后

console.log(CHORD_REGEX); // will output regexp mentioned at the beginning of the answer

它对我很有用。

【讨论】:

    【解决方案2】:

    我已经从以前的答案中改进了一些答案,以帮助我的情况。现在它在诗句的开头忽略了一些“可能的和弦”(如A,E)。 这是我出来的:

    (\(*[CDEFGAB](?:b|bb)*(?:#|##|sus|maj|min|aug|m|M|°|[0-9])*[\(]?[\d\/]*[\)]?(?:[CDEFGAB](?:b|bb)*(?:#|##|sus|maj|min|aug|m|M|°|[0-9])*[\d\/]*)*\)*)(?=[\s|$])(?! [a-z])
    

    【讨论】:

      【解决方案3】:

      这通过使用您的示例输入并达到您所有的“超级奖励积分”要求:

      String output = input.replaceAll("(?m)(^| )([A-G](##?|bb?)?((sus|maj|min|aug|dim)\\d?)?(/[A-G](##?|bb?)?)?)( (?!\\w)|$)", "[$2]");
      

      这段代码把它变成了(作为一个带有嵌入线路费用的字符串):

      Db    Dsus4/F#           A            Cbmin/C
      A man can't be asked for that much to do
      D/F#        G         A           D#/E
      And I can't sweep you off of your feet
      

      进入这个:

      [Db]  [Dsus4/F#]         [A]          [Cbmin/C]
      A man can't be asked for that much to do
      [D/F#]      [G]       [A]         [D#/E]
      And I can't sweep you off of your feet
      

      【讨论】:

      • 非常酷——目前它不是在开始时保持对齐吗?
      • 否 - 正如您从输出中看到的那样,通过在开头插入 [,整个和弦线向右移动了一个字符。为了避免这种情况,必须在行首的和弦后面消耗一个额外的空格(即2个空格)。虽然老实说,[ 现在标志着和弦的开始,对齐看起来很好 - 也许就按原样使用它。顺便说一句,您可能会发现 Apache commons-io FileUtils.readFileToString()writeStringToFile() 很方便
      • 我正在尝试在 R 中实现这一点。但我无法让它工作。我的 regex101 示例抛出错误 / An unescaped delimiter must be escaped with a backslash (\) regex101.com/r/3NbIwi/1
      • @Ratnanil 正斜杠字符在正则表达式中没有特殊含义,但许多语言使用正斜杠来 delimit 正则表达式,我怀疑 R 就是这样一种语言。尝试在我的正则表达式中的每个正斜杠之前放置一个反斜杠。如果这不起作用,请在每个正斜杠之前尝试一个双反斜杠。
      【解决方案4】:

      代码在我检查的示例中很好地执行了协议,并且 Agreements simplesles 7th agreement with sharp or flat like C# 7

      string strRegex = @"^[A-G]([5679bm#]([57])?|1[13]|6\/9|7[-#+b][59]|7?sus[24]|add[249]|aug|dim7?|m\/maj7|m1[13]|m[679]|m7?b5|maj1[13]|maj[79])?([\/][A-G]([5679bm#])?([57])?)?";
      
      Regex myRegex = new Regex(strRegex, RegexOptions.None);
      string strTargetString = @"A";
      string strReplace = @"[$0]";
      
      return myRegex.Replace(strTargetString, strReplace);
      

      【讨论】:

      • 仅供参考,这是一个 java 问题
      • @Eric 奇怪的是,另一个用户添加了 Java,因为我的问题实际上是一个一般的正则表达式问题。我意识到最后的替换需要选择语言,但任何人都可以做到。也就是说,我认为这使真正的需求过于复杂......因为我不想证明无效的和弦(dim35 等),所以这里有很多额外的检查。如果有人要解析细节,这可能会非常有用。
      【解决方案5】:

      对于您提供的案例,我有一些有效的正则表达式,但不确定它如何适用于其他人。问题是一行可以以A开头,也可以在歌曲行中。我尝试使用负前瞻来解决它,检查和弦后面是否跟着空格和字母数字。如果有空格和字母数字,我们不匹配这个和弦。由于和弦可以在/ 之后重复,所以我将模式加倍。

      \b([CDEFGAB](?:b|bb)*(?:#|##|sus|maj|min|aug)*[\d\/]*(?:[CDEFGAB](?:b|bb)*(?:#|##|sus|maj|min|aug)*[\d\/]*)*)(?=\s|$)(?! \w)

      看看the demo

      【讨论】:

      • 这真是太棒了。我也在添加我忘记的“m”选项。 (?&lt;=\b)([CDEFGAB](?:b|bb|m)*(?:#|##|sus|maj|min|aug)*[\d\/]*(?:[CDEFGAB](?:b|bb|m)*(?:#|##|sus|maj|min|aug)*[\d\/]*)*)(?=\s|$)(?! \w)
      • 请注意,如果和弦之间只有 1 个空格,可能会有问题。也许,我们可以使用(?! [^ CDEFGAB])lookahead 使其更安全。
      • fyi (?&lt;=\b)\b 相同,因为两者都不消耗输入。这也将匹配 "Auugmin" 或 A####### - 使用 ?而不是 *
      猜你喜欢
      • 2012-08-28
      • 2022-01-25
      • 2011-07-24
      • 2016-03-03
      • 1970-01-01
      • 1970-01-01
      • 2011-01-04
      • 2019-11-19
      • 2016-12-09
      相关资源
      最近更新 更多