2010-06-03 5 views
6

Estoy en proceso de crear una pestaña de guitarra para el convertidor rtttl (Ring Tone Text Transfer Language) en PHP. Para preparar una pestaña de guitarra para la conversión rtttl, primero elimino todos los comentarios (los comentarios se anotaron con # y terminaron con - #), luego tengo algunas líneas que establecen el tempo, tomo nota del ajuste y defino múltiples instrumentos (Tempo 120 \ nDefina Guitar 1 \ nDefina Bass 1, etc etc.) que se eliminan de la pestaña y se reservan para un uso posterior.pestaña php regex para guitarra (pestañas o tablatura, un tipo de notación musical)

Ahora, básicamente, no me queda nada excepto las pestañas de la guitarra. Cada pestaña está precedida de su nombre de instrumento junto con el nombre del instrumento anotado anteriormente.

Algunas veces tenemos pestañas para 2 instrumentos separados que están vinculados porque deben tocarse juntos, es decir, una guitarra y un bajo tocando juntos.

Ejemplo 1, Standard Guitarra:

|Guitar 1 
e|--------------3-------------------3------------| 
B|------------3---3---------------3---3----------| 
G|----------0-------0-----------0-------0--------| 
D|--------0-----------0-------0-----------0------| 
A|------2---------------2---2---------------2----| 
E|----3-------------------3-------------------3--| 

Ejemplo 2, conjunción Tab:

|Guitar 1 
e|--------------3-------------------3------------| 
B|------------3---3---------------3---3----------| 
G|----------0-------0-----------0-------0--------| 
D|--------0-----------0-------0-----------0------| 
A|------2---------------2---2---------------2----| 
E|----3-------------------3-------------------3--| 
| 
| 
|Bass 1 
G|----------0-------0-----------0-------0--------| 
D|--------2-----------2-------2-----------2------| 
A|------3---------------3---3---------------3----| 
E|----3-------------------3-------------------3--| 

he considerado otros métodos de identificación de las pestañas sin resultados sólidos. Espero que alguien que haga expresiones regulares me ayude a encontrar una forma de identificar una sola pestaña de guitarra y, si es posible, también pueda hacer coincidir una pestaña con múltiples instrumentos unidos entre sí.

Una vez que las pestañas están en una matriz, las examinaré una línea a la vez y las convertiré en líneas rtttl (explotadas en cada nueva línea "\ n").

No quiero separar las pestañas de guitarra en el documento mediante la explosión "\ n \ n" o algo similar porque no identifica la pestaña de guitarra, sino que identifica el espacio entre las pestañas, no en el pestañas ellos mismos.

He estado jugando con esto durante aproximadamente una semana y esta es la única retención importante que tengo. Todo lo demás es bastante simple.

A partir de la corriente, he intentado muchas variaciones del patrón de expresiones regulares. Aquí está una de las más recientes muestras de prueba:

<?php 
$t = " 
|Guitar 1 
e|--------------3-------------------3------------| 
B|------------3---3---------------3---3----------| 
G|----------0-------0-----------0-------0--------| 
D|--------0-----------0-------0-----------0------| 
A|------2---------------2---2---------------2----| 
E|----3-------------------3-------------------3--| 

|Guitar 1 
e|--------------3-------------------3------------| 
B|------------3---3---------------3---3----------| 
G|----------0-------0-----------0-------0--------| 
D|--------0-----------0-------0-----------0------| 
A|------2---------------2---2---------------2----| 
E|----3-------------------3-------------------3--| 
| 
| 
|Bass 1 
G|----------0-------0-----------0-------0--------| 
D|--------2-----------2-------2-----------2------| 
A|------3---------------3---3---------------3----| 
E|----3-------------------3-------------------3--| 

"; 

preg_match_all("/^.*?(\\|).*?(\\|)/is",$t,$p); 
print_r($p); 

?> 

También vale la pena señalar que dentro de las pestañas, ¿dónde están los guiones y # 's, usted también puede tener cualquier variación de letras, números y puntuacion. El comienzo de cada línea marca la afinación de cada cuerda con uno de los siguientes casos insensibles: a, a #, b, c, C#, d, d #, e, f, f #, g o g.

Gracias de antemano por su ayuda con este problema tan difícil.

+0

¿Entendí bien, que quieren una matriz en donde cada elemento sería la línea de un instrumento? –

+0

No, eso es lo que haré después de separar cada pestaña. ¿Te das cuenta de que tengo la Guitarra 1, luego la Guitarra 1 y la Grave 1 arriba? Me gustaría que la primera Guitar 1 esté en $ array [0], y la Guitar 1 y Bass 1 estén en $ array [1], etc. para que cada sección o medida (o w/e la llame) de la pestaña podría ser separado Después de esta separación, puedo analizar a través de cada línea de cada pestaña para convertirla a rtttl - cada línea se convertirá a la vez a través de str_replace y funciones similares. – John

Respuesta

5

Me gusta mucho esta pregunta :-P. Me divertí descifrando esto.
Aquí es lo que tengo:

<?php 
$t = <<<EOD 
|Guitar 1 
e|--------------3-------------------3------------| 
B|------------3---3---------------3---3----------| 
G|----------0-------0-----------0-------0--------| 
D|--------0-----------0-------0-----------0------| 
A|------2---------------2---2---------------2----| 
E|----3-------------------3-------------------3--| 

|Guitar 1 
e|--------------3-------------------3------------| 
B|------------3---3---------------3---3----------| 
G|----------0-------0-----------0-------0--------| 
D|--------0-----------0-------0-----------0------| 
A|------2---------------2---2---------------2----| 
E|----3-------------------3-------------------3--| 
| 
| 
|Bass 1 
G|----------0-------0-----------0-------0--------| 
D|--------2-----------2-------2-----------2------| 
A|------3---------------3---3---------------3----| 
E|----3-------------------3-------------------3--| 

EOD; 


GetTabs($t); 

function GetTabs($tabString) { 
    $tabs = array(); 
    $tabcount = 0; 
    $instrumentcount = 0; 
    $tabline = 0; 

    $tabStringArray = explode("\n", $tabString); 

    foreach ($tabStringArray as $tabStringRow) { 

     if (preg_match ('/^(?<snaretuningprefix>[bgdaeBGDAE#])+\|(?<tabline>[0-9-]+)\|/', $tabStringRow)) { 
      //Matches a tab line 
      //The tabline group can be expanded with characters for hammer on's, pull off's and whatnot 
      $tabs[$tabcount][$instrumentcount-1][$tabline] = $tabStringRow; 
      $tabline++; 
      continue; 
     } 

     if (preg_match ('/^\s\|\s+/', $tabStringRow, $matches)) { 
      //Matches ' |' 
      //Continuation of tab do nothing 
      continue; 
     } 

     if (preg_match ('/^\s\|(?<instrument>[A-z0-9\s]+)/', $tabStringRow, $matches)) { 
      //Matches an instrument line ' |Guitar 1' 

      $tabs[$tabcount][$instrumentcount]['instrumentname'] = $matches['instrument']; 
      $instrumentcount++; 
      $tabline = 0; 
      continue; 
     } 

     if (preg_match ('/^\s+/', $tabStringRow)) { 
      //Matches empty line 
      //new tab 

      $tabcount++; 
      $instrumentcount = 0; 

      continue; 
     } 

    } 

    print_r($tabs); 
} 


?> 

La función se comentó algo, que no es tan difícil de leer, creo.
este salidas:

Array 
(
    [0] => Array 
     (
      [0] => Array 
       (
        [instrumentname] => Guitar 1 
        [0] => e|--------------3-------------------3------------| 
        [1] => B|------------3---3---------------3---3----------| 
        [2] => G|----------0-------0-----------0-------0--------| 
        [3] => D|--------0-----------0-------0-----------0------| 
        [4] => A|------2---------------2---2---------------2----| 
        [5] => E|----3-------------------3-------------------3--| 
       ) 

     ) 

    [1] => Array 
     (
      [0] => Array 
       (
        [instrumentname] => Guitar 1 
        [0] => e|--------------3-------------------3------------| 
        [1] => B|------------3---3---------------3---3----------| 
        [2] => G|----------0-------0-----------0-------0--------| 
        [3] => D|--------0-----------0-------0-----------0------| 
        [4] => A|------2---------------2---2---------------2----| 
        [5] => E|----3-------------------3-------------------3--| 
       ) 

      [1] => Array 
       (
        [instrumentname] => Bass 1 
        [0] => G|----------0-------0-----------0-------0--------| 
        [1] => D|--------2-----------2-------2-----------2------| 
        [2] => A|------3---------------3---3---------------3----| 
        [3] => E|----3-------------------3-------------------3--| 
       ) 

     ) 

) 
+0

¡Fuera de la caja esto es perfecto! Aunque aún no entiendo el código dinámico: D ¡El resultado de salida es absolutamente lo que necesito! ¡¡Gracias por ayudar!! – John

0

El^en su expresión regular evitará que el modificador/s haga lo que desee.

Además, preg_match_all va a devolver muchas "coincidencias" duplicadas porque está utilizando la agrupación(). Si planea usar preg_match_all() en un archivo con varias pestañas, aislar coincidencias reales puede ser difícil con esos duplicados.

+0

Sí, creo que fue uno de los problemas que tuve sin darme cuenta. Solo entiendo la expresión regular más básica en este momento, pero me estoy poniendo al día. He podido hacer coincidir cadenas y lo que no en el pasado, ¡pero los caracteres escapados realmente me desanimaron! ¡Gracias por aclarar! – John

1
<?php 
$t = <<<EOD 
|Guitar 1 
e|--------------3-------------------3------------| 
B|------------3---3---------------3---3----------| 
G|----------0-------0-----------0-------0--------| 
D|--------0-----------0-------0-----------0------| 
A|------2---------------2---2---------------2----| 
E|----3-------------------3-------------------3--| 

|Guitar 1 
e|--------------3-------------------3------------| 
B|------------3---3---------------3---3----------| 
G|----------0-------0-----------0-------0--------| 
D|--------0-----------0-------0-----------0------| 
A|------2---------------2---2---------------2----| 
E|----3-------------------3-------------------3--| 
| 
| 
|Bass 1 
G|----------0-------0-----------0-------0--------| 
D|--------2-----------2-------2-----------2------| 
A|------3---------------3---3---------------3----| 
E|----3-------------------3-------------------3--| 

EOD; 

$t = preg_replace('/\r\n?/', "\n", $t); //normalize line endings 

$te = explode("\n", $t); 

$out = array(); 
$cur_inst = ""; 
$trim = false; 
$lastlines = array(); 
$i = 0; 
foreach ($te as $line) { 
    if (preg_match("/^\\s\\|(\\w+ \\d+)\$/", $line, $matches)) { 
     if ($matches[1] == $cur_inst) { 
      $trim = true; 
     } 
     else { 
      $out[$i++] = $line; 
      $trim = false; 
      $lastline = array(); 
      $cur_inst = $matches[1]; 
     } 
    } 
    elseif (empty($line) || preg_match("/^\\s\\|\$/", $line)) { 
     if (!preg_match("/^\\s\\|\$/", end($out))) 
      $out[$i++] = $line; 
    } 
    elseif (preg_match("/^([a-zA-Z])\\|(.*)\$/", $line, $matches)) { 
     if ($trim) { 
      if (array_key_exists($matches[1], $lastlines)) { 
       $oldi= $lastlines[$matches[1]]; 
       $out[$oldi] = rtrim($out[$oldi], "|") . $matches[2]; 
      } 
      else { 
       die("unexpected line: $line"); 
      } 
     } 
     else { 
      $lastlines[$matches[1]] = $i; 
      $out[$i++] = $matches[0]; 
     } 
    } 
    else { 
     die("unexpected line: $line"); 
    } 
} 

$t = implode(PHP_EOL, $out); 

echo $t; 

da

 
|Guitar 1 
e|--------------3-------------------3--------------------------3-------------------3------------| 
B|------------3---3---------------3---3----------------------3---3---------------3---3----------| 
G|----------0-------0-----------0-------0------------------0-------0-----------0-------0--------| 
D|--------0-----------0-------0-----------0--------------0-----------0-------0-----------0------| 
A|------2---------------2---2---------------2----------2---------------2---2---------------2----| 
E|----3-------------------3-------------------3------3-------------------3-------------------3--| 

| 
|Bass 1 
G|----------0-------0-----------0-------0--------| 
D|--------2-----------2-------2-----------2------| 
A|------3---------------3---3---------------3----| 
E|----3-------------------3-------------------3--| 

Si lo prefiere, puede iterar sobre la matriz $out.

+0

Correcto, esto es lo que básicamente haré una vez que obtenga cada "sección" de pestaña separada del documento. El problema es que lo más probable es que haya algunas variaciones entre cada "sección" de pestañas y separar las secciones según lo que entre ellas puede no ser confiable. es decir, si alguien tiene letras entre pestañas, podría romperse. (ok, mal ejemplo, pero creo que entiendes lo que estoy tratando de señalar). Gracias por la entrada. Si no tengo otro éxito, tendré que recurrir a esto. – John

+0

@John Luego cambie el último 'else' a, en lugar de morir, ignorando las líneas que no reconoce. – Artefacto

+0

oh, ya veo. No noté la barra de desplazamiento antes. Esto parece ser válido. Lo probaré más cuando tenga oportunidad. ¡Gracias por toda tu ayuda! – John

1

no estoy del todo seguro de qué es exactamente lo que quieres decir, pero si desea separar las pestañas por instrumento, intente esto:

^[^|\r\n]+\|([^|\r\n]+)$\r?\n # match the line that contains the instrument name 
           # and capture this in backreference 1 
(        # capture the block of lines that follows 
(?:       # repeat this for each line 
    ^[^|\r\n]+     # everything up to the first | 
    \|       # | 
    [^|\r\n]+     # everything up to the next | 
    \|       # | 
    \r?\n      # newline 
)+       # at least once 
)        # end capture 

En PHP:

preg_match_all('/^[^|\r\n]+\|([^|\r\n]+)$\r?\n((?:^[^|\r\n]+\|[^|\r\n]+\|\r?\n)+)/im', $subject, $result, PREG_PATTERN_ORDER); 
for ($i = 0; $i < count($result[0]); $i++) { 
    # Matched text = $result[0][$i]; 
} 

Cada partido será de el formulario

|Bass 1 
G|----------0-------0-----------0-------0--------| 
D|--------2-----------2-------2-----------2------| 
A|------3---------------3---3---------------3----| 
E|----3-------------------3-------------------3--| 

y todo lo demás entre esos bloques será ignorado.

+0

¡Esto se ve perfecto! Muchas gracias! Voy a probarlo e informar cualquier éxito/fracaso. Estoy dispuesto a compartir mi código con cualquier persona que esté interesada también una vez que termine. ¡Gracias de nuevo! – John

+0

Tras la prueba inicial, no encontré resultados. Eliminé la primera parte de la cadena de expresiones regulares que me diste y coincide perfectamente con las pestañas reales: /((?:^[^ | \ R \ n] + \ | [^ | \ r \ n] + \ | \ r? \ n) +)/im Pero la parte anterior a eso (la parte que identificó el instrumento) parecía ser la culpable. Cuando ejecuté la cadena completa de expresiones regulares, recibí 3 matrices vacías como resultados. No he probado en profundidad hasta el momento, pero el otro ejemplo de PHP/comentario a continuación parece estar funcionando! ¡Gracias por toda su ayuda! – John

Cuestiones relacionadas