2015-03-19 11 views
5

Sto provando ad aggiungere parentesi quadre su accordi in documenti di testo standard formattati per chitarra/testi per renderli più compatibili con l'app OnSong. Ho le regole ma non capisco come abbinare per tutte le possibili combinazioni. Le regole sono:Regex per il bracket di accordi/accordi di chitarra standard

  • Chords inizierà con un singolo AG capitale
  • se l'AG capitale è seguito da uno spazio, rottura del cavo, #, B, M, sus, agosto, fioca, maj, min, o/Mi piacerebbe leggere fino al prossimo spazio o interruzione di riga (a causa della formattazione standard della chitarra, un accordo come F # min/E è possibile, e piuttosto che preoccuparsi di dividere tutto, voglio solo continuare a leggere fino allo spazio)
  • La regex NON deve corrispondere se la capital AG è seguita da un'altra lettera non presente nell'elenco (ad esempio il nome "Ed" non deve corrispondere)
  • punti bonus se riesci a capire come fare " Un piccolo mondo "NON corrisponde alla parola SEGUENDO che la" A "non è un accordo valido.
  • punti super bonus se la sostituzione può rimuovere uno spazio prima (quando non si avvia una linea) e dopo le nuove parentesi (per mantenere l'allineamento in posizione) - mi è stato fatto notare che questo non funzionerà su accordi ravvicinati ... questo è completamente accettabile.

Un paio di note: questo è per uno script di supporto ... la perfezione non è necessaria. Lo faccio a mano proprio ora, quindi la miss occasionale va bene. Non sto cercando di analizzare i dettagli degli accordi, solo per avvolgerli in []. Mentre il layout standard è costituito da 1 riga di accordi, 1 riga di testo, questo non può essere conteggiato, quindi sono consapevole che alcuni scenari falliranno occasionalmente.

fonte di prova (accordi sono casuali a scopo di test, nel caso in cui eventuali musicisti stavano per carillon in sulla musica terribile):

Db Dsus4/F#   A   Cbmin/C 
A man can't be asked for that much to do 
D/F#  G   A   D#/E 
And I can't sweep you off of your feet 

dovrebbe girare in:

[Db] [Dsus4/F#]   [A]   [Cbmin/C] 
A man can't be asked for that much to do 
[D/F#]  [G]  [A]   [D#/E] 
And I can't sweep you off of your feet 

Il mio primo tentativo mi ha stretto con:

([A-G]((?!\s).)*) 

ma che ha raccolto parole che sono iniziate con quelle lettere anche. Ho fatto il giro in tondo ora e solo ottenuto per quanto riguarda:

\b([CDEFGAB](#|##|b|bb|sus|maj|min|aug)?\b) 

Quando ho provato ad utilizzare [^\s+] ottengo risultati misti che raccogliere più di ciò che voglio, ma anche fosso cose che ho bisogno. Penso di essere appena sopra la mia testa. Qualsiasi aiuto sarebbe GRANDE apprezzato e qualsiasi spiegazione su come funziona sarebbe ancora meglio. Anche se mi piacerebbe una soluzione, mi piacerebbe anche molto spiegare perché funziona ...

+0

Così 'A # Eb // Oh uomo' 'diventerà [A #] [Eb] // Oh uomo'!? A causa della vicinanza di questi accordi, perdiamo l'allineamento (aggiungendo le parentesi). – zessx

+0

Buon punto sugli accordi uno contro l'altro ... a volte l'allineamento non funzionerà - Ho accettato quel destino :) – IglooWhite

+0

Con quale linguaggio o strumento userete la regex? E cos'è questo animale? –

risposta

5

Questo passa usando il vostro ingresso campione e raggiunge tutte le vostre esigenze "punti bonus super":

String output = input.replaceAll("(?m)(^|)([A-G](##?|bb?)?((sus|maj|min|aug|dim)\\d?)?(/[A-G](##?|bb?)?)?)((?!\\w)|$)", "[$2]"); 

Questo codice trasforma questo (come una singola stringa con canoni di linea incorporati):

Db Dsus4/F#   A   Cbmin/C 
A man can't be asked for that much to do 
D/F#  G   A   D#/E 
And I can't sweep you off of your feet 

In questo:

[Db] [Dsus4/F#]   [A]   [Cbmin/C] 
A man can't be asked for that much to do 
[D/F#]  [G]  [A]   [D#/E] 
And I can't sweep you off of your feet 
+0

molto cool - NON sta mantenendo l'allineamento all'avvio al momento? – IglooWhite

+0

No: come si può vedere dall'output, l'intera linea di accordo viene spostata di un carattere a destra con l'inserimento di '[' all'inizio. Per evitare ciò, si dovrebbe consumare uno spazio extra (cioè 2 spazi) seguendo un accordo all'inizio della linea. Anche se, a dire il vero, l'allineamento sembra buono con il simbolo '[che ora segna l'inizio dell'accordo - forse lo si usa così com'è. BTW potresti trovare Apache commons-io 'FileUtils.readFileToString()' e 'writeStringToFile()' handy – Bohemian

2

Ho alcune regex di lavoro per il caso che hai fornito, ma non sono sicuro di come funzionerà per gli altri. Il problema è che una linea può iniziare con A, oppure può essere nella riga della canzone. Ho cercato di aggirarlo usando il lookahead negativo controllando se l'accordo è seguito da uno spazio e un alfanumerico. Se c'è uno spazio e un alfanumerico, non concordiamo con questo accordo. Poiché gli accordi possono essere ripetuti dopo lo /, sto raddoppiando il pattern.

\b([CDEFGAB](?:b|bb)*(?:#|##|sus|maj|min|aug)*[\d\/]*(?:[CDEFGAB](?:b|bb)*(?:#|##|sus|maj|min|aug)*[\d\/]*)*)(?=\s|$)(?! \w)

Dai un'occhiata alla the demo.

+0

Questo è veramente eccellente. Aggiungo anche l'opzione 'm' che ho dimenticato. '([CDEFGAB] (?: b | bb | m) * ((<= \ b?):?? # | ## | sus | maj | min | agosto) * [\ d \ /] * ([ CDEFGAB] (?: b | bb | m) *? (:? # | ## | sus | maj | min | agosto) * [\ d \ /] *) *) (= \ s | $) (?! \ w) ' – IglooWhite

+0

Ricorda che potrebbe esserci un problema se c'è solo 1 spazio tra gli accordi. Forse, possiamo renderlo più sicuro con '(?! [^ CDEFGAB])' lookahead. –

+0

fyi '(? <= \ B)' è identico è solo '\ b', poiché nessuno dei due consuma input. Anche questo corrisponderebbe "Aaugmin" o A ####### - utilizzare? invece di * – Bohemian

0

il codice esegue bene l'accordo nel campione che ho controllato e Agreem Ent simplesles 7th accordi con calante o come C# 7

string strRegex = @"^[A-G]([5679bm#]([57])?|1[13]|6\/9|7[-#+b][59]|7?sus[24]|add[249]|aug|dim7?|m\/maj7|m1[13]|m[679]|m7?b5|maj1[13]|maj[79])?([\/][A-G]([5679bm#])?([57])?)?"; 

Regex myRegex = new Regex(strRegex, RegexOptions.None); 
string strTargetString = @"A"; 
string strReplace = @"[$0]"; 

return myRegex.Replace(strTargetString, strReplace); 
+0

fyi questa è una domanda * java * – Bohemian

+0

@Eric stranamente, un altro utente ha aggiunto Java al mix, poiché la mia domanda era davvero un problema generale Regex. Mi rendo conto che la sostituzione alla fine richiede una scelta linguistica, ma chiunque potrebbe davvero farlo. Detto questo, penso che questo superi il vero bisogno ... dal momento che non sto cercando di dimostrare accordi non validi (dim35 o simili) c'è un sacco di controlli extra in corso qui. Questo sarebbe probabilmente molto utile se qualcuno stesse per analizzare i dettagli. – IglooWhite

0

ho migliorato un po 'la risposta dalla risposta precedente per aiutare nel mio caso. Ora ignorava alcuni "accordi probabilmente" quando è all'inizio del verso (come A, E). Questo quello che mi è venuto fuori:!

(\(*[CDEFGAB](?:b|bb)*(?:#|##|sus|maj|min|aug|m|M|°|[0-9])*[\(]?[\d\/]*[\)]?(?:[CDEFGAB](?:b|bb)*(?:#|##|sus|maj|min|aug|m|M|°|[0-9])*[\d\/]*)*\)*)(?=[\s|$])(?! [a-z]) 
Problemi correlati