9

我正在尝试编写一个函数来解析音乐和弦的字符串表示。

示例:C 大调和弦 -> Cmaj(这是我要解析的)

为了清楚起见,和弦由三个不同的部分组成:

  • 音符(C、D、E、F、G、A)
  • 该音符的临时记号(#、##、b、bb)
  • 和弦名称

对于那些精通音乐的人,我不考虑斜线和弦(故意)。

以下功能几乎可以正常工作。但是它仍然不适用于以下情况:

  • "C#maj" # 匹配并且应该
  • "C#maj7" # 匹配并且应该
  • "C#maj2" #数学运算,不应该

我想如果我可以让chords正则表达式部分被强制放在正则表达式的末尾,那就成功了。我试过$在这个字符串之前和之后都使用它,但它没有用。

任何的想法?谢谢。

public static void regex(String chord) {                
    String notes = "^[CDEFGAB]";
    String accidentals = "[#|##|b|bb]";
    String chords = "[maj7|maj|min7|min|sus2]";
    String regex = notes + accidentals + chords; 
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(chord);
    System.out.println("regex is " + regex);
    if (matcher.find()) {
        int i = matcher.start();
        int j = matcher.end();
        System.out.println("i:" + i + " j:" + j);           
    }
    else {
        System.out.println("no match!");
    }
}
4

4 回答 4

2

在以下几行中更改[](和:)

String accidentals = "(#|##|b|bb)";
String chords = "(maj7|maj|min7|min|sus2)";

否则,您只是在制作字符类,因此[maj7|maj|min7|min|sus2]只需在 letter 上进行匹配m

我猜你也想添加一个结束锚$?我看到您之前遇到过问题,但这可能是由于上述问题。


另外,您是否希望(#|##|b|bb)成为可选的(即,使用?: (#|##|b|bb)?)?

于 2012-06-27T14:59:38.457 回答
2

原谅 JavaScript,但就纯粹的 REGEX 而言,这种模式似乎有效。您没有规定在哪个和弦名称之后允许哪些数字,但我假设 2 仅在“sus”之后允许,7 仅在“min”和“maj”之后允许。

var chords = "C#maj7 C##maj Bbmaj7 Abmin2 Cbmin Dsus";
var valid_chords = chords.match(/\b[CDEFGAB](?:#{1,2}|b{1,2})?(?:maj7?|min7?|sus2?)\b/g);
于 2012-06-27T15:07:21.780 回答
1

基于 Wiseguy 的回答,我改进了您的正则表达式匹配。由于抛出匹配,我不得不#在变量之外添加。accidentals\b#

奖励:它甚至可以匹配 Dsus9、D7 等和弦。

原谅 JavaScript,但这是我最终使用的代码:

var notes = "[CDEFGAB]",
  accidentals = "(b|bb)?",
  chords = "(m|maj7|maj|min7|min|sus)?",
  suspends = "(1|2|3|4|5|6|7|8|9)?",
  sharp = "(#)?",
  regex = new RegExp("\\b" + notes + accidentals + chords + suspends + "\\b" + sharp, "g");

var matched_chords = "A# is a chord, Bb is a chord. But H isn't".match(regex);

console.log(matched_chords);

于 2017-10-02T08:57:16.887 回答
0

我没有足够的声誉来评论 Amit 的帖子。

这就是我用来做这个的。重要的是在“m”之前检查“maj”和“min”,否则像 C#m 这样的和弦会出现错误匹配。从技术上讲,这将允许像 C#9000 这样的和弦,但我猜这在你的情况下不会有太大问题。

[A-G](b|#)?(maj|min|m|M|\+|-|dim|aug)?[0-9]*(sus)?[0-9]*(\/[A-G](b|#)?)?
于 2020-07-06T19:03:39.027 回答