ShoeLace1291
ShoeLace1291

Reputation: 4698

How to validate a musical note with regex

I am trying to validate user input that should be a valid note. In music, notes are letters A-G and can be either sharp(#) or flat(b). Notes don't have to be sharp or flat, they can be natural. Why is this regex not matching the # or b in any of the notes? Here is a regex101 demo.

([A-G]{1})(\#|b{1})?

Here is a list of all inputs that should match:

A
A#
Ab
B
Bb
C
C#
Cb
D
D#
Db
E
Eb
F
F#
Fb
G
G#
Gb

P.S. E# and B# don't exist in music, so I'll have to program that into my code.

Upvotes: 3

Views: 510

Answers (2)

acdcjunior
acdcjunior

Reputation: 135772

Your regex:

([A-G]{1})(\#|b{1})?

Is correct.

To make your demo work, you need to remove the x modifier, as it affects # chars (it is a confusing modifier, actually). When you remove it, it shows your regex works (updated demo here).

About the x modifier:

x modifier: Ignore whitespace

This flag tells the engine to ignore all whitespace and allow for comments in the regex. Comments are indicated by a starting "#"-character.

Now, if I may, you can simplify it by removing those {1}, they are redundant (they default is match once already). Also, as noted by CSᵠ (see comment below), that # doesn't need escaping and then \#|b could become [#b]:

([A-G])([#b])?

Of course, if you don't need to match the note (the first group) or the sharp/flat symbols (the second group) individually, you can remove parentheses as well.

Other than that, you can add the gm modifiers to test multiple lines: DEMO here.


Bonus:

You don't have to program, you can not match E# and B# using regex only:

(?![EB]#)([A-G])([#b])?

This demo shows it working. The (?! ... ) is known as negative lookahead.

Upvotes: 3

Avinash Raj
Avinash Raj

Reputation: 174706

You must need to include anchors and also you have to enable multiline modifier m.

^([A-G]{1})(\#|b{1})?$

or

^[A-G][#b]?$

DEMO

Upvotes: 0

Related Questions