jal
jal

Reputation: 533

Regex to validate letters and numbers doesn't work as expected

I'm trying to create a regular expression that contains 17 characters, must have mandatory numbers and letters, and must not contain the letters I, O, Q, Ñ. At the moment I have got:

^(([a-h]|[j-n]|p|[r-z]|[A-H]|[J-N]|P|[R-Z]|[0-9]){17})$

But if I type only numbers or only letters, the regular expression validates it as good.

Upvotes: 1

Views: 263

Answers (2)

Guffa
Guffa

Reputation: 700342

Use positive and negative look-aheads to require and disallow characters:

/^(?=.*[0-9])(?=.*[A-Za-z])(?!.*[ioqñIOQÑ])[0-9a-zA-Z]{17}$/.test(s);

Demo: http://jsfiddle.net/2mNyg/

Description:

(?=.*[0-9])        - requires a digit
(?=.*[A-Za-z])     - requires a letter
(?!.*[ioqñIOQÑ])   - disallows all characters in the set
[0-9a-zA-Z]{17}    - allow basic set and require 17 characters

Note: The look-ahead that requires a letter will also be satisfied by the disallowed characters, but the look-ahead that disallows the characters will still stop it. That way you can make the expression simpler.

Upvotes: 3

Jon
Jon

Reputation: 437376

Generally in such cases you want to use positive lookahead in order to assert that the input satisfies additional conditions. Since you have two conditions here (must contain at least one number, must contain at least one letter), this translates to two different lookaheads.

Together with extra whitespace and "comments" for readability the regex should look like this:

^
(?=.*[a-hj-npr-zA-HJ-NPR-Z].*)  // assert the input contains at least one letter
(?=.*[0-9].*)                   // assert the input contains at least one digit
[a-hj-npr-zA-HJ-NPR-Z0-9]{17}   // existing condition (17 allowed chars exactly)
$

Upvotes: 4

Related Questions