4

这是这个问题的后续问题:Regex for matching a music Chord,由我提出。

现在我有一个正则表达式可以知道String和弦的表示是否有效(上一个问题),我怎样才能有效地将和弦的三个不同部分(根音、临时记号和弦类型)转换为单独的变量?

我可以做简单的字符串操作,但我想在前面的代码上构建并使用正则表达式会更容易,还是我错了?

以下是上述问题的更新代码:

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

3 回答 3

3

用括号括起来(除了具有特殊含义的情况)会创建一个捕获组或子模式。

您已经拥有accidentalschords分组为这样的子模式,但您需要添加括号以notes将其捕获为子模式。

String notes = "^([CDEFGAB])";
String accidentals = "(#|##|b|bb)?";
String chords = "(maj7|maj|min7|min|sus2)";

按照惯例,与整个模式匹配的字符串是组 0,然后每个子模式被捕获为组 1、组 2,依此类推。

我不是 Java 人,但在阅读了文档之后,您似乎可以使用以下方式访问您的子模式匹配.group()

String note = matcher.group(1);
String acci = matcher.group(2);
String chor = matcher.group(3);

编辑:

最初,我建议String accidentals = "((?:#|##|b|bb)?)";,因为我担心如果不存在匹配的第二个子模式是可选的,会导致组编号问题。然而,一些测试表明,即使没有将它包装在这样的非捕获分组(?: )中,组 2 也始终存在,但如果没有匹配项则为空。(无论如何,第 2 组中的空字符串是想要的效果。)所以,这似乎 ... = "(#|##|b|bb)?";就足够了。

于 2012-06-27T15:31:08.757 回答
2

你已经完成了这项工作。只需再添加一个捕获组,您的最终正则表达式就变为:

    ^([CDEFGAB])(#|##|b|bb)?(maj7|maj|min7|min|sus2)?$

您的音符、变音记号和和弦将分别出现在第一、第二和第三次捕捉中。

于 2012-06-27T15:32:20.973 回答
2

我喜欢公认的答案,但作为一名吉他手,我确实会遇到添加了额外低音音符的和弦,例如 G/D、A/D 或 D/F#。当然,您可能会遇到许多其他和弦名称,例如:5 , 6, min6, 9, min9, sus4 ... 等。您可以考虑添加可能的字符串和弦的数量,然后添加一些贝斯临时记号,如果你有的话:

String chords =
"(maj|maj7|maj9|maj11|maj13|maj9#11|maj13#11|6|add9|maj7b5|maj7#5||min|m7|m9|m11|m13|
m6|madd9|m6add9|mmaj7|mmaj9|m7b5|m7#5|7|9|11|13|7sus4|7b5|7#5|7b9|7#9|7b5b9|7b5#9|
7#5b9|9#5|13#11|13b9|11b9|aug|dim|dim7|sus4|sus2|sus2sus4|-5|)";
String bass = "/([CDEFGAB])";

为了完成“弦乐和弦”的定义,您可能需要查阅和弦词典。干杯!

于 2013-01-17T07:24:50.510 回答