这是对此问题的后续问题: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!");
}
}
感谢。
答案 0 :(得分:3)
用括号括起内容(具有特殊含义的情况除外)会创建capturing group或子模式。
您已将accidentals
和chords
分组为此类子模式,但您需要将括号添加到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)?";
可能就足够了。
答案 1 :(得分:2)
你已经完成了这项工作。只需添加一个捕获组,以便最终的正则表达式成为:
^([CDEFGAB])(#|##|b|bb)?(maj7|maj|min7|min|sus2)?$
你的音符,偶然和和弦将分别在第一,第二和第三次捕捉中。
答案 2 :(得分: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])";
为了完成“字符串和弦”定义,您可能需要咨询chord dictionary。干杯!