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|#)?)?
Другие вопросы по тегам