I am trying to add square brackets around chords in standard text documents formatted for guitar/lyrics to make them more compatible with the OnSong app. I have the rules but don't understand how to match for all the possible combinations. The rules are:
A couple notes: This is for a helper script... perfection is not needed. I do this by hand right now, so the occasional miss is okay. I'm not trying to parse out the details of the chords, just to wrap them in []. While the standard layout is 1 row of chords, 1 row of lyrics, this can't be counted on, so I'm aware some scenarios will fail occasionally.
Test source (chords are random for testing purposes, in case any musicians were going to chime in on the terrible music):
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
Should turn into:
[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
My first attempt got me close with:
([A-G]((?!\s).)*)
but that picked up words that began with those letters as well. I have gone around in circles now and only gotten as far as:
\b([CDEFGAB](#|##|b|bb|sus|maj|min|aug)?\b)
When I've tried to use [^\s+]
I get mixed results that pick up more of what I want but also ditch things I need. I think I'm just over my head. Any help would be GREATLY appreciated and any explanation of how it works would be even better. While I'd like a solution, I'd also really love to explain why it works...
This passes using your sample input and achieves all your "super bonus points" requirements:
String output = input.replaceAll("(?m)(^| )([A-G](##?|bb?)?((sus|maj|min|aug|dim)\\d?)?(/[A-G](##?|bb?)?)?)( (?!\\w)|$)", "[$2]");
This code turns this (as a single String with embedded line fees):
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
Into this:
[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
I have some working regex for the case you provided, but not sure how it will work for others. The problem is that a line can start with A
, or it can be in the song line. I tried to work around it using the negative lookahead checking if the chord is followed by a space and an alphanumeric. If there is a space and an alphanumeric, we do not match this chord. Since the chords can repeat after /
, I am doubling the pattern.
\b([CDEFGAB](?:b|bb)*(?:#|##|sus|maj|min|aug)*[\d\/]*(?:[CDEFGAB](?:b|bb)*(?:#|##|sus|maj|min|aug)*[\d\/]*)*)(?=\s|$)(?! \w)
Have a look at the demo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With