Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex to validate custom format

Tags:

java

regex

I have this format: xx:xx:xx or xx:xx:xx-y, where x can be 0-9 a-f A-F and y can be only 0 or 1.

I come up with this regex: ([0-9A-Fa-f]{2}[:][0-9A-Fa-f]{2}[:][0-9A-Fa-f]{2}|[-][0-1]{1})

(See regexr).

But this matches 0a:0b:0c-3 too, which is not expected.

Is there any way to remove these cases from result?

like image 964
D.T Avatar asked Jan 26 '26 19:01

D.T


2 Answers

[:] means a character from the list that contains only :. It is the same as :. The same for [-] which has the same result as -.
Also, {1} means "the previous piece exactly one time". It does not have any effect, you can remove it altogether.

To match xx:xx:xx or xx:xx:xx-y, the part that matches -y must be optional. The quantifier ? after the optional part mark it as optional.

All in all, your regex should be like this:

[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}(-[01])?

If the regex engine you use can be told to ignore the character case then you can get rid of A-F (or a-f) from all character classes and the regex becomes:

[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}(-[01])?

How it works, piece by piece:

[0-9a-f]      # any digit or letter from (and including) 'a' to 'f'
{2}           # the previous piece exactly 2 times
:             # the character ':'
[0-9a-f]
{2}
:
[0-9a-f]
{2}
(             # start a group; it does not match anything
  -           # the character '-'
  [01]        # any character from the class (i.e. '0' or '1')
)             # end of group; the group is needed for the next quantifier
?             # the previous piece (i.e. the group) is optional
              # it can appear zero or one times

See it in action: https://regexr.com/4rfvr

Update

As @the-fourth-bird mentions in a comment, if the regex must match the entire string then you need to anchor its ends:

^[0-9a-f]{2}:[0-9a-f]{2}:[0-9a-f]{2}(-[01])?$

^ as the first character of a regex matches the beginning of the string, $ as the last character matches the end of the string. This way the regex matches the entire string only (when there aren't other characters before or after the xx:xx:xx or xx:xx:xx-y part).

If you use the regex to find xx:xx:xx or xx:xx:xx-y in a larger string then you don't need to add ^ and $. Of course, you can add only ^ or $ to let the regex match only at the beginning or at the end of the string.

like image 128
axiac Avatar answered Jan 29 '26 09:01

axiac


You want

xx:xx:xx or if it is followed by a -, then it must be a 0 or 1 and then it is the end (word boundry).

So you don't want any of these

0a:0b:0c-123
0a:0b:0cd
10a:0b:0c

either.

Then you want "negative lookingahead", so if you match the first part, you don't want it to be followed by a - (the first pattern) and it should end there (word boundary), and if it is followed by a -, then it must be a 0 or 1, and then a word boundary:

/\b([0-9a-f]{2}[:][0-9a-f]{2}[:][0-9a-f]{2}(?!-)\b|\b[0-9a-f]{2}[:][0-9a-f]{2}[:][0-9a-f]{2}-[01]\b)/i

To prevent any digit in front, a word boundary is added to the front as well.

Example: https://regexr.com/4rg42

The following almost worked:

/\b([0-9a-f]{2}[:][0-9a-f]{2}[:][0-9a-f]{2}\b[^-]|\b[0-9a-f]{2}[:][0-9a-f]{2}[:][0-9a-f]{2}-[01]\b)/i

but if it is the end of file and it is 3a:2b:11, then the [^-] will try to match a non - character and it won't match.

Example: https://regexr.com/4rg4q

like image 42
nonopolarity Avatar answered Jan 29 '26 08:01

nonopolarity



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!