2012-06-27 2 views
8

Я пытаюсь написать функцию для синтаксического анализа строкового представления музыкального аккорда.Regex для соответствия музыке Chord

Пример: C мажорный аккорд ->CMAJ (это то, что я хочу, чтобы разобрать)

Просто чтобы понять, аккорд состоит из трех различных частей:

  • ПРИМЕЧАНИЯ (С, D, Е, F, G, а)
  • в случайности для этой записки (#, ##, б, бб)
  • название аккорда

Для тех, кто подружился с музыкой, я не рассматриваю аккорды слэш (специально).

Нижняя функция почти работает. Однако он по-прежнему не работает в следующих случаях:

  • "C#" # Maj матчи и должны
  • "C#" # maj7 матчи и должны
  • "C# maj2" # mathches и не должны

Я полагаю, что если бы я мог сделать 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!"); 
    } 
} 
+0

Узор между 'C# maj2' и' C# maj7' одинаково (C# maj \ d), поэтому дифференцирование между ними на самом деле не является заданием для регулярного выражения. Я бы захватил все экземпляры этого шаблона, а затем использовал несколько шаблонов строк для проверки. Однако вы можете создать регулярное выражение, которое включает все принятые цифры в виде литералов. –

+0

Я бы сделал статические коллекции, содержащие все возможные аккорды. Посмотрите, найдено ли строковое представление в Коллекциях. – hovanessyan

+0

«... Для тех, музыкальных подкованных, я не рассматриваю слэш-аккорды ...» Только для записи: вы игнорируете * most * аккорды, а не только косые аккорды. –

ответ

2

Изменения [ и ] к ( и ) в следующих строках:

String accidentals = "(#|##|b|bb)"; 
String chords = "(maj7|maj|min7|min|sus2)"; 

В противном случае вы просто делаете классы персонажей, так [maj7|maj|min7|min|sus2] просто совпадают с буквой m.

Я предполагаю, что вы также хотите добавить конечный якорь $? Я вижу, что у вас были проблемы с этим раньше, но это, вероятно, из-за вышеупомянутой проблемы.


Кроме того, возможно, вы хотите (#|##|b|bb) быть факультативным (то есть, с ?: (#|##|b|bb)?)?

2

Простите JavaScript, но в чисто REGEX-точке этот шаблон работает. Вы не указали, какие номера разрешены, после чего имена аккордов, но я предположил, что 2 разрешено только после «суса» и 7 только после «мин» и «май».

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); 
+1

Это регулярное выражение работает хорошо – grimmdude

0

Основываясь на ответе Wiseguy, я улучшил соответствие регулярных выражений. Я должен был добавить # вне переменной accidentals с \b throws соответствия # выключен.

Bonus: Он даже соответствует аккорды как 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);

Смежные вопросы