(?=(.*\W.*){0,})
is not 0 non-alphanumeric characters. It is at least 0 non-alphanumeric characters. If you wanted the password to not contain any non-alphanumeric characters you could do either (?!.*\W)
or (?=\w*$)
.
A simpler solution would be to skip the \W
look-ahead, and use \w{8,}
instead of .{8,}
.
Also, \w
includes \d
. If you wanted just the alpha you could do either [^\W\d]
or [A-Za-z]
.
/^(?=(?:.*?\d){2})(?=(?:.*?[A-Za-z]){2})\w{8,}$/
This would validate the password to contain at least two digits, two alphas, be at least 8 characters long, and contain only alpha-numeric characters (including underscore).
\w
= [A-Za-z0-9_]
\d
= [0-9]
\s
= [ \t\n\r\f\v]
Edit:
To use this in all browsers you probably need to do something like this:
var re = new RegExp("^(?=(?:.*?\\d){2})(?=(?:.*?[A-Za-z]){2})\\w{8,}$");
if (re.test(password)) { /* ok */ }
Edit2: The recent update in the question almost invalidates my whole answer. ^^;;
You can should still be able to use the javascript code in the end, if you replace the pattern with what you had originally.
Edit3: OK. Now I see what you mean.
/^(?=.*[a-z].*[a-z])(?=.*[0-9].*[0-9]).{3,}/.test("password123") // matches
/^(?=.*[a-z].*[a-z])(?=.*[0-9].*[0-9]).{4,}/.test("password123") // does not match
/^(?=.*[a-z].*[a-z]).{4,}/.test("password123") // matches
It seems (?= )
isn't really zero-width in IE.
http://development.thatoneplace.net/2008/05/bug-discovered-in-internet-explorer-7.html
Edit4: More reading: http://blog.stevenlevithan.com/archives/regex-lookahead-bug
I think this can solve your problem:
/^(?=.{8,}$)(?=(?:.*?\d){2})(?=(?:.*?[A-Za-z]){2})(?=(?:.*?\W){1})/
new RegExp("^(?=.{8,}$)(?=(?:.*?\\d){2})(?=(?:.*?[A-Za-z]){2})(?=(?:.*?\\W){1})")
The (?=.{8,}$)
needs to come first.