Could anyone help me with a regex for a password with the following please.
include at least two of the following:
a lowercase letter
a capital letter
a number
a 'special character' (e.g. £, $, &, #)
Could anyone help me with a regex for a password with the following please.
include at least two of the following:
a lowercase letter
a capital letter
a number
a 'special character' (e.g. £, $, &, #)
The following should work:
^(?![a-z]*$|[A-Z]*$|\d*$|[\W_]*$).*$
Example: http://www.rubular.com/r/effCmvehdx
The negative lookahead at the beginning will cause this to fail if the entire string is composed entirely of just one group.
Note that even though this fits your requirements, this is not a very good regex for a strong password. You probably also want a length check and you may want to require at least three of those groups instead of two.
As Keith Thompson said in a comment, I don't think a single regex is worth here.
The following code will do what you want, and I think it is more readable, maintainable and easier to prove the correctness than a single regular expression:
string password = "123abc";
string[] regexes = new[]
{
"[a-z]", //any lowercase word
"[A-Z]", //any uppercase word
@"\d", //any digit
@"\W" //special characters (or just [£$&#], adding the characters you want)
};
bool isValid = regexes.Count(regex => Regex.IsMatch(password, regex)) >= 2;
As I said in a comment, a regex is almost certainly not the right tool for this job. It's going to be much easier to write some code that iterates over the characters of the password, counting the number of characters in each class.
You haven't defined what a "special character" is. I'll assume that it means any character other than a letter or digit (which would include spaces and control characters). I'm also assuming that "letters" refers to just the 26 letters of the English alphabet -- which means that a non-English letter like ñ
is a special character.
To take a simpler example, regexes aren't very good at expressing things like "foo and bar in either order"; you have to specify both order explicitly:
foo.*bar|bar.*foo
In this case, you need 12 different choices. I think this is correct, but I haven't tested it.
[a-z].*[A-Z}|[A-Z].*[a-z}|[a-z].*[0-9]|[0-9].*[a-z]|[a-z].*[^a-zA-Z0-9]|[^a-zA-Z0-9].*[a-z]|[A-Z].*[0-9]|[0-9].*[A-Z]|[A-Z].*[^a-zA-Z0-9]|[^a-zA-Z0-9].*[A-Z]|[0-9].*[^a-zA-Z0-9]|[^a-zA-Z0-9].*[0-9]
This is an egrep-style or Perl-style regex. grep
doesn't recognize |
by default; if you need a grep
-style regexp, replace each |
by \|
.
And if the requirements change, say requiring at least 3 out of 5 classes of characters, you'll need to completely rewrite the regex; you can't just tweak it.
Note that your requirements still permit Aa
.