2012-06-27 22 views
8

Estoy tratando de escribir una función para analizar la representación de cuerda de un acorde musical.Regex para hacer coincidir un acorde de música

Ejemplo: acorde de Do mayor ->Cmaj (esto es lo que quiero analizar)

Sólo para que quede claro, un acorde se compone de tres partes diferentes:

  • la nota (C, D, E, F, G, A)
  • las alteraciones para esa nota (#, ##, b, bb)
  • el nombre del acorde

Para aquellos, conocedores de la música, no estoy considerando acordes de corte (a propósito).

La siguiente función está casi funcionando. Sin embargo, todavía no funciona para el siguiente caso:

  • "C#" # maj partidos y debe
  • "C#" # Maj7 partidos y debe
  • "C# Maj2" # mathches y no debería

supongo que si podía hacer la parte chords expresiones regulares obligados a estar al final de la expresión regular, hizo el truco. He intentado usar el $ tanto antes como después de esta cadena, pero no funcionó.

¿Alguna idea? Gracias.

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

El patrón entre 'C# maj2' y' C# maj7' es idéntico (C# maj \ d), por lo que diferenciarlos no es realmente un trabajo para regex. Me gustaría tomar todas las instancias de ese patrón y luego usar algunos patrones de cadena más para validar. Sin embargo, podría compilar una expresión regular que incluya todos los dígitos aceptados como literales. –

+0

Haría colecciones estáticas que contienen todos los acordes posibles. Que ver si la representación de cadena se encuentra en las Colecciones. – hovanessyan

+0

"... Para aquellos, conocedores de la música, no estoy considerando los acordes de corte ..." Solo para el registro: Estás ignorando * la mayoría * de los acordes, no solo los acordes de corte. –

Respuesta

2

Cambio [ y ] a ( y ) en las siguientes líneas:

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

De lo contrario sólo estás haciendo clases de personajes, por lo [maj7|maj|min7|min|sus2] partidos simplemente en la carta m.

Supongo que también quiere agregar un ancla final $? Veo que tuviste problemas con eso antes, pero eso es probablemente debido al problema antes mencionado.


También, puede ser que le quieren (#|##|b|bb) a ser opcional (es decir, con ?: (#|##|b|bb)?)?

2

Perdone el JavaScript, pero en un punto puramente REGEX, este patrón parece funcionar. No estipulaste qué números están permitidos después de qué nombres de acordes, pero supongo que 2 solo está permitido después de 'sus' y 7 solo después de 'min' y '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

Esta expresión regular funciona bien – grimmdude

0

Basándome en la respuesta de Wiseguy, mejoré su correspondencia con la expresión regular. Tuve que agregar # fuera de la variable accidentals desde \b arroja coincidencias # off.

Bono: Incluso coincide acordes como Dsus9, etc. D7

Perdona el JavaScript, pero este es el código que terminé usando:

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

Cuestiones relacionadas