Reputation: 21389
I am trying to write a function to parse the string representation of a musical chord.
Example: C major chord -> Cmaj (this is what I want to parse)
Just to make it clear, a chord is made of three different parts:
For those, music savvy, I am not considering slash chords (on purpose).
The below function is almost working. However it still doesn't work for the following case:
I suppose that if I could make the chords
regex part forced to be at the end of the regex, did the trick. I have tried using the $
both before and after this String but it didn't work.
Any idea? Thanks.
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!");
}
}
Upvotes: 11
Views: 3743
Reputation: 183
I don't have enough reputation to comment on Amit's post.
This is what I used for this. The important thing is to check for 'maj' and 'min' before 'm' otherwise there will be false matches on chords like C#m. Technically this would allow for chords like C#9000, but I'm guessing that won't be much of a problem in your case.
[A-G](b|#)?(maj|min|m|M|\+|-|dim|aug)?[0-9]*(sus)?[0-9]*(\/[A-G](b|#)?)?
Upvotes: 0
Reputation: 1670
Building on Wiseguy's answer, I improved your regex matching. I had to add #
outside of the variable accidentals
since \b
throws matching #
off.
Bonus: It even matches chords like Dsus9, D7 etc.
Forgive the JavaScript, but this is the code I ended up using:
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);
Upvotes: 2
Reputation: 34556
Forgive the JavaScript, but on a purely REGEX point, this pattern seems to work. You didn't stipulate which numbers are allowed after which chord names but I've assumed 2 is allowed only after 'sus' and 7 only after 'min' and '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);
Upvotes: 2
Reputation: 20883
Change [
and ]
to (
and )
in the following lines:
String accidentals = "(#|##|b|bb)";
String chords = "(maj7|maj|min7|min|sus2)";
Otherwise you're just making character classes, so [maj7|maj|min7|min|sus2]
simply matches on the letter m
.
I'm guessing you also want to add an ending anchor $
? I see you had problems with that before, but that's probably because of the aforementioned issue.
Also, might you want (#|##|b|bb)
to be optional (i.e., with ?
: (#|##|b|bb)?
)?
Upvotes: 1