2012-06-27 36 views
8

Tôi đang cố gắng viết một hàm để phân tích chuỗi đại diện của hợp âm nhạc.Regex để phù hợp với một âm nhạc hợp âm

Ví dụ: C lớn âm ->Cmaj (đây là những gì tôi muốn phân tích)

Chỉ cần để làm cho nó rõ ràng, một hợp âm được làm bằng ba phần khác nhau:

  • các lưu ý (C, D, E, F, G, A)
  • các accidentals cho lưu ý rằng (#, ##, b, bb)
  • tên hợp âm

Đối với những người, âm nhạc hiểu biết, tôi không xem xét hợp âm chém (trên mục đích).

Chức năng dưới đây gần như hoạt động. Tuy nhiên nó vẫn không hoạt động đối với trường hợp sau đây:

  • "C# maj" # trận đấu và nên
  • "C# maj7" # trận đấu và nên
  • "C# maj2" # mathches và không nên

tôi giả sử rằng nếu tôi có thể làm cho một phần chords regex buộc phải ở phần cuối của regex, đã làm các trick. Tôi đã thử sử dụng $ cả trước và sau chuỗi này nhưng nó không hoạt động.

Bất kỳ ý tưởng nào? Cảm ơn.

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ác mô hình giữa 'C# maj2' và' C# maj7' giống hệt nhau (C# maj \ d), vì vậy sự khác biệt giữa chúng không thực sự là một công việc cho regex. Tôi sẽ lấy tất cả các trường hợp của mẫu đó và sau đó sử dụng một số mẫu chuỗi khác để xác thực. Tuy nhiên, bạn có thể xây dựng một regex bao gồm tất cả các chữ số được chấp nhận làm chữ. –

+0

Tôi sẽ tạo các bộ sưu tập tĩnh chứa tất cả các hợp âm có thể. Hơn xem nếu đại diện chuỗi được tìm thấy trong Bộ sưu tập. – hovanessyan

+0

"... Đối với những người, âm nhạc hiểu biết, tôi không xem xét hợp âm chém ..." Chỉ cần cho hồ sơ: Bạn đang bỏ qua * hầu hết * hợp âm, không chỉ cắt giảm hợp âm. –

Trả lời

2

Thay đổi [] để () trong những dòng sau:

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

Nếu không, bạn chỉ cần làm cho lớp nhân vật, vì vậy [maj7|maj|min7|min|sus2] đơn giản phù hợp trên bức thư m.

Tôi đoán bạn cũng muốn thêm một neo kết thúc $? Tôi thấy bạn đã có vấn đề với điều đó trước đây, nhưng đó có thể là do vấn đề nói trên.


Ngoài ra, bạn có thể muốn (#|##|b|bb) là tùy chọn (ví dụ, với ?: (#|##|b|bb)?)?

2

Hãy tha thứ cho JavaScript, nhưng trên một điểm REGEX hoàn toàn, mẫu này có vẻ hoạt động. Bạn đã không quy định những con số nào được cho phép sau khi có tên hợp âm nhưng tôi đã giả định 2 chỉ được phép sau 'sus' và 7 chỉ sau 'min' và '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); 
+1

Regex này hoạt động tốt – grimmdude

0

Xây dựng dựa trên câu trả lời của Wiseguy, tôi đã cải thiện kết hợp regex của bạn. Tôi đã phải thêm # ngoài biến số accidentals kể từ \b ném khớp với số # tắt.

Bonus: Nó thậm chí phù hợp với hợp âm như Dsus9, D7, vv

Hãy tha thứ cho JavaScript, nhưng đây là đoạn code tôi đã kết thúc bằng:

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

Các vấn đề liên quan