How to allow underscore in this 'Password Complexity' regex
Here it is:
/(?=^.{8,}$)((?=.开发者_开发技巧*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/
It only passes if the password contains upper case AND lower case letters, and also either 1 digit or 1 special character, however I want underscore _ to count as a special character as well and it currently does not, how can modify this regex so that it will allow underscore to count as a special character?
EDIT: here is the context...
jQuery.validator.addMethod("complexity", function(value, element) {
return this.optional(element) || /(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/.test(value);
}, "password is not complex, see requirements above");
/(?=^.{8,}$)((?=.*\d)|(?=.*[\W_]+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/
aioobe was close replace \W with [\W_]
Just so you know this considers a space a special character.
Also I don't see where you are checking for numbers. EDIT: nevermind I found it. (man complex regexes are like a wheres waldo.)
Here is a simplifed version that does not allow spaces (and it is easyier to maintain)
(?=^.{8,}$)(?=.*[a-z])(?=.*[A-Z])(?=.*[\W_])(?=^.*[^\s].*$).*$
^ ^ ^ ^ ^
| | | | L--does not contain a whitespace
| | | L--at least one non word character(a-zA-Z0-9_) or _ or 0-9
| | L--at least one upper case letter
| L--at least one lowercase Letter
L--Number of charaters
These are your building blocks
(?=.*[a-z]) // Whatever is inside the [] meens the string contains at least one charter inside that set.
// If you wanted a minimum of three lowercase letters you can chain the inner block like so
(?=(.*[a-z]){3,})
Any particular reason you want to do all of this in one regex? Seems to me this would be a lot more readable if you just broke it down:
if (password.length() < 8) return "Password too short!";
if (!password.matches("\d")) return "Password must contain at least one digit!";
if (!password.matches("[A-Z]")) return "Password must contain at least one uppercase leter!";
if (!password.matches("[a-z]")) return "Password must contain at least one lowercase leter!";
// Password is valid, save it, etc.
I suppose your \W
denotes a special character (It's usually defined as "A non-word character")
So, if you would like to add _
to that set of characters, you should be able to write [\W_]
.
(Updated according to Scott Chamberlains comment.)
I'm not sure why you have (?![.\n])
. Do you want to prevent newlines in the password?
Otherwise, this looks like a simplified regexp:
String regexp = "(?=^.{8,}$)(?=.*[A-Z])(?=.*[a-z])(?=.*[\\W_\\d]).*$";
for (String s : new String[] {
"abcdefg",
"abcdefgh",
"abCdefgh",
"abc1efgh",
"abC1efgh",
"abC1e@gh",
"abC1e_gh"}) {
System.out.println(s + " is " + (s.matches(regexp) ? "ok" : "not ok"));
}
Prints
abcdefg is not ok
abcdefgh is not ok
abCdefgh is not ok
abc1efgh is not ok
abC1efgh is ok
abC1e@gh is ok
abC1e_gh is ok
Do you consider this an acceptable password?
Aa8 ½ý_
Because your regex matches it. You might want to change that first lookahead from (?=^.{8,}$)
to (?=^[!-~]{8,}$)
, limiting the possibilities to printing ASCII characters (i.e., not whitespace or control characters). If you want to allow non-ASCII characters it gets a lot more complicated; JavaScript regexes don't do Unicode very well.
Here's how I would write the regex:
/^(?=[!-~]{8,}$)(?=.*[A-Z])(?=.*[a-z])(?=.*[^A-Za-z]).*$/
Like Scott, I don't see the point of this bit: (?![.\n])
. All it does is make sure the first character is not a period or a linefeed. That can't be what you (or the original author) meant, but I can't even guess what the actual intent was.
For future searchers, here's my implementation that includes requiring a special character AND a digit:
/(?=^[!-~]{8,}$)(?=.*[a-z])(?=.*[A-Z])(?=.*[^A-Za-z0-9])(?=^.*[^\s].*$)(?=.*[\d]).*$/
Heres an example
精彩评论