3

I'm trying to build up a regex pattern for the html input field which only allows up to 20 combined alphabetical letters and digits which can only have up to two of Dashes(-), Underscores(_) and fullstops (.)

So something like only two of the symbols allowed and any amount of letters and digits allowed, combined they've got to be between 4 and 20.

What would the pattern for this be?

An sample (non functioning) version could be like [A-Za-z0-9([\._-]{0,2})]{4,20}

Solution:

I decided to go with @pascalhein @Honore Doktorr answer which is to use a lookahead. The final pattern is ^(?=[A-Za-z0-9]*([._-][A-Za-z0-9]*){0,2}$)[A-Za-z0-9._-]{4,20}$

user3254198
  • 763
  • 6
  • 23

2 Answers2

5

You can verify the length with a lookahead at the beginning:

^(?=.{4,20}$)

Then list all the cases that are allowed for your regex separately:

[A-Za-z0-9]* (no special chars)

[A-Za-z0-9]*[._-][A-Za-z0-9]* (one special char)

[A-Za-z0-9]*[._-][A-Za-z0-9]*[._-][A-Za-z0-9]* (two special chars)

It isn't beautiful, but I believe it should work. This is the final expression:

^(?=.{4,20}$)([A-Za-z0-9]*|[A-Za-z0-9]*[._-][A-Za-z0-9]*|[A-Za-z0-9]*[._-][A-Za-z0-9]*[._-][A-Za-z0-9]*)$

Edit:

Actually, it might be nicer to test the number of special characters with a lookahead instead:

^(?=[A-Za-z0-9]*([._-][A-Za-z0-9]*){0,2}$)[A-Za-z0-9._-]{4,20}$
pascalhein
  • 5,700
  • 4
  • 31
  • 44
  • Very elegant! I tried to answer this question, but I was stuck on how to limit the length of the total string while allowing a flexible number of alphanumeric characters. Nicely explained, too. – Joe DeRose May 19 '15 at 16:08
  • 1
    @pascalhein: alternatively, assert that there are no more than two special characters w/ a negative lookahead, `(?!(?:.*[-_.]){3,}`. Full expression `^(?=.{4,20}$)(?!(?:.*[-_.]){3,})[-_.a-zA-Z0-9]*$`, [sample](http://refiddle.com/refiddles/555b618e75622d5b8e080400). – Honore Doktorr May 19 '15 at 16:10
  • @celerno I tested at regexr.com, but is there a problem with what you are showing? As I understand, it should not be matched because it contains 4 special characters and only 2 are allowed – pascalhein May 19 '15 at 16:22
0

I encourage you to not to use a Regex when there are functions for the porpuse you want to achieve.

An advice I give to jrs on this topic is to use a regex for single porpuses, if there is more than one porpuse, use more regex.

to answer your question:

  • 1 your valid characters from start to end.

    var 1stregex = /^[A-Za-z0-9._-]{4,20}$/;

  • 2 Count must be 0 to 2, which in javascript is .match().length.

    var 2ndregex = /([._-])/;

    if(myText.match(1stregex) && myText.match(2ndregex).length <=2) { isvalid=true; }

celerno
  • 1,367
  • 11
  • 30
  • I can see where you're coming from but as I'm trying to use this with HTML's pattern tag to have more support and avoid having to write actual code for validation I decided to use a regex instead. – user3254198 May 19 '15 at 16:12
  • sometimes is better (in terms of clean code and time spent) to write a few lines. my opinion. – celerno May 19 '15 at 16:19