Regex для соответствия музыкального аккорда
Я пытаюсь написать функцию для анализа строкового представления музыкального аккорда.
Пример: 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!");
}
}
3 ответа
+ Изменить [
а также ]
в (
а также )
в следующих строках:
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);
Опираясь на ответ Висеги, я улучшил соответствие ваших регулярных выражений. Я должен был добавить #
вне переменной 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);
У меня недостаточно репутации, чтобы комментировать пост Амита.
Вот что я для этого использовал. Важно проверять наличие "maj" и "min" перед "m", иначе на аккордах, таких как C#m, будут ложные совпадения. Технически это позволило бы использовать аккорды, подобные C#9000, но я предполагаю, что в вашем случае это не будет большой проблемой.
[A-G](b|#)?(maj|min|m|M|\+|-|dim|aug)?[0-9]*(sus)?[0-9]*(\/[A-G](b|#)?)?