2012-06-27 3 views
3

Это следующий вопрос к этому вопросу: Regex for matching a music Chord, заданный мной.Music Chord part splitting Regex

Теперь у меня есть регулярное выражение, чтобы знать 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!"); 
    } 
} 

Спасибо.

ответ

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

Edit:

Первоначально, Я предложил String accidentals = "((?:#|##|b|bb)?)";, потому что я был обеспокоен тем, что второй подшаблон, являющийся необязательным, вызвал бы проблему нумерации групп, если для нее не существовало соответствия. Тем не менее, небольшое тестирование предполагает, что даже без обертывания его в группе без захвата (?:) группа 2 всегда присутствует, но пуста, если совпадения не было. (Пустая строка в группе 2 в любом случае была желательным эффектом.) Итак, кажется, что ... = "(#|##|b|bb)?";, вероятно, хватит в конце концов.

+0

+1 - Гораздо лучше, чем мой ответ. –

+0

Догадка, что я был прав, думая, что есть лучший способ, а не строковая манипуляция. спасибо за второй раз сегодня – nunos

2

Вы уже выполнили эту работу. Просто добавьте еще одну группы захвата, так что ваше окончательное регулярное выражение становится:

^([CDEFGAB])(#|##|b|bb)?(maj7|maj|min7|min|sus2)?$ 

И ваша записку, случайно, и аккорд будет в первых, втором и третьих захватах, соответственно.

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 , CHEERS!