What am I missing?
The reasons your tests '2@2qwert' and '2@@qwert' are incorrectly matching your regex is because there isn't anything in it that requires a minimum of 6 lowercase letters. Based on the other answers and comments to this question, I'd say replace your (?=.*[a-z]) clause with (?=(.*?[a-z]){6}).
Some other minor improvements that can be made:
- You can drop the redundant
(?=.*[^a-z]) clause since all this is saying is that the string should contain at least 1 non-letter, which is already established by the digit and special character requirement.
- Replace [0-9] with \d.
- In the 3 places where you are matching wildcards prior to a character match (.*), it is slightly faster for the RegExp engine if these are made non-greedy so that there is less backtracking done when searching through the string for a match. This is done by placing a ? after the * (.*?).
Putting this together based on your regexp:
/^(?=.*?\d)(?=(.*?[a-z]){6})(?=.*?[@#$*])\S{8,}$/
This successfully matches your first 4 strings, but not the last 2.
(My original response is below in case you want a readable validate function.)
function validate(str)
{
// test for digit
if( !/\d/.test(str) ) return false;
// test for special character
if( !/[@#$*]/.test(str) ) return false;
// test for 6 lowercase letters
var letters = str.match(/[a-z]/g);
return letters != null && letters.length == 6;
}
var tests = [ '2@qwerty', '#1asddfg', 'qwe*yt2u', '#qw2wqia', '2@2qwert', '2@@qwert' ];
for( var i=0 ; i<tests.length ; ++i )
document.writeln(tests[i] + ": " + validate(tests[i]) + "<br/>\n");