1
\$\begingroup\$

I had a problem a few days back and had to find a regex that matches a string that:

  • Contains only letters in the alphabet [a-z0-9-] so lowercase latin letters, numbers 0 to 9, and the dash character
  • Must contains at least a letter [a-z]
  • Must not contains repeating dashes. abc-def-gh is ok but not abc--def
  • The size of the string must be between 1 and 10 characters

I came up with:

^(?=[a-z0-9-]*[a-z][a-z0-9-]*)(?:[a-z0-9]|[-](?![-])){1,10}$

A little explanation:

  • (?=[a-z0-9-]*[a-z][a-z0-9-]*) lookahead to find if the string contains at least a letter
  • (?:[a-z0-9]|[-](?![-])){1,10} A non capturing group (not really important to capture or not I believe) with two parts, that must be between 1 and 10 chars
    • [a-z0-9] any letter in the alphabet I want
    • [-](?![-] a dash then a negative lookahead to see if there is no dash following

Here is a list of strings that should not match:

#should not match
-
1
1-
-1
aaaaaaaaaaaaaaaaa
11111
2a2--af
a2a--22

And a list of string that should match:

#should match
a
a-
-a
a-2
a2a
2a2-
a2a-2a2
a-b-c-d
a123213232
123213213a
a12321322a

HERE you can find an online regex tester to play with it.

All improvements, remarks, feedbacks is welcome. My guts is telling me the lookahead can be improved but I did not find how. Also, I'm not even sure the lookahead is needed at all. I'm eager to improve my regex skill so if you have any alternative method also I'd be really glad to know.

\$\endgroup\$
  • 1
    \$\begingroup\$ by "Must not contain repeating dashes", do you mean "no more than one dash total" or "no consecutive dashes"? i.e. should it match abc-def-ghi? the current regex doesn't match that. \$\endgroup\$ – cas Jan 13 '18 at 10:34
  • \$\begingroup\$ Yes I mean no a--a but abc-chd-dhd should work \$\endgroup\$ – Julien Rousé Jan 13 '18 at 10:37
  • \$\begingroup\$ In the regex tester, I believe it matches abc-def-gh? It doesn't work with abc-def-ghi because it's too long and the string should be 10 maximum. see here at the bottom \$\endgroup\$ – Julien Rousé Jan 13 '18 at 10:43
  • 1
    \$\begingroup\$ doh, you're right. i didn't think to count the chars, and typed too fast to notice it change when i typed the 10th character. \$\endgroup\$ – cas Jan 13 '18 at 10:44
  • \$\begingroup\$ No worries, thanks for your input! And in the comment I told you were right when it wasn't, I didn't check either if abc-def-ghi was too long, my mistake. \$\endgroup\$ – Julien Rousé Jan 13 '18 at 10:45
1
\$\begingroup\$

The lookahead (?=[a-z0-9-]*[a-z][a-z0-9-]*) can be reduce to:

(?=.*[a-z])

because the allowed characters are defined after in the non capturing group.

The dash [-] doesn't need to be inside a character class, - is enough

Then, the whole regex becomes:

^(?=.*[a-z])(?:[a-z0-9]|-(?!-)){1,10}$
\$\endgroup\$
  • \$\begingroup\$ Thank you for your help! Was there any way to get rid of that lookahead? \$\endgroup\$ – Julien Rousé Jan 13 '18 at 11:22
  • 1
    \$\begingroup\$ @JulienRousé: No, it is the simplest way to do such checking. \$\endgroup\$ – Toto Jan 13 '18 at 11:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.