我正在尝试编写一个函数来解析音乐和弦的字符串表示。
示例: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!");
}
}
以下行中将[
和]
更改为(
和)
:
String accidentals = "(#|##|b|bb)";
String chords = "(maj7|maj|min7|min|sus2)";
否则,您只是在制作字符类,因此[maj7|maj|min7|min|sus2]
只需在字母m
上匹配即可。
我猜你还想添加一个结束锚$
?我看到你以前有问题,但这可能是因为上述问题。
另外,您是否希望(#|##|b|bb)
是可选的(即,使用 ?
: (#|##|b|bb)?
)?
原谅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);
基于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);
我没有足够的声誉来评论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|#)?)?