Reputation: 1074
How can I construct a regular expression such that a password field I am making contains at least one number, at least one lowercase letter and at least one uppercase letter where order DOES NOT matter and anything can be in-between these characters?
I have tried this and got something similar: ".*\\d.*[a-z].*[A-Z].*"
but that requires that the number comes first, the lowercase second and the uppercase last.
Upvotes: 1
Views: 448
Reputation: 1778
Yours is not one of the use case regular expressions are particularly good at – if you're stuck with regular expressions, I guess you have no choice but to enumerate the 6 cases:
.*[0-9].*[a-z].*[A-Z].*|.*[0-9].*[A-Z].*[a-z].*|.*[a-z] ... | ...
Check with actual java code would be easier (and more readable):
String password = "";
boolean complies = password.matches(".*[0-9].*")
&& password.matches(".*[a-z].*")
&& password.matches(".*[A-Z].*");
or (uglier, but possibly faster):
boolean complies = false;
{
boolean hasDigit = false;
boolean hasLowercase = false;
boolean hasUppercase = false;
for (int i = 0; i < password.length(); i++) {
char c = password.charAt(i);
hasDigit |= '0' <= c && c <= '9';
hasLowercase |= 'a' <= c && c <= 'z';
hasUppercase |= 'A' <= c && c <= 'Z';
if (hasDigit && hasLowercase && hasUppercase) {
complies = true;
break;
}
}
}
Upvotes: 3
Reputation: 1963
One way to achieve this is by
1) First check for the presence of lower case letter by using a separate regex, say regex-1.
2) Next check if it contains numbers by using another regex.
3) Check for any other rule.
Breaking down the rules would solve the issue you are facing and also improves the way you report the error.
Upvotes: 3
Reputation: 299218
Regex is not suited for complicated scenarios like this. The only way you can implement it in regex is by listing all possibilities:
(abc|acb|bac|bca|cab|cba)
Where a, b, and c are sub-patterns that represent your individual requirements, e.g. abc
would be .*\\d.*[a-z].*[A-Z].*
, bac
stands for [a-z].*.*\\d.*[A-Z].*
, etc. Good luck in maintaining such a monster. My tip would be to create java constants for each of the parts:
private static final String DI = "\\d+";
private static final String LO = "[a-z]+";
private static final String UP = "[A-Z]+";
private static final String WI = ".*";
private static final String OR = "|";
private static final Pattern REGEX = Pattern .compile(
WI + DI + WI + LO + WI + UP + WI + OR
+ WI + LO + WI + DI + WI + UP + WI + OR
// etc
);
Upvotes: 1