The pattern does not meet your specifications, because the quantifiers {1}
, {2}
are applied to . and not to the right pattern. Also, the last quantifier {8,}
allows any number of characters from 8, but you need to cap their number to 20. Also, note that {1}
is totally redundant. Besides, I suggest using the principle of contrast inside the lookaheads (check Lookahead Example: Simple Password Validation).
You can use
final String PASSWORD_PATTERN =
"^(?=[^0-9]*[0-9])(?=(?:[^A-Za-z]*[A-Za-z]){2})(?=[^@#$%^&+=]*[@#$%^&+=])\\S{8,20}$";
See regex demo
Explanation:
^
- string start
(?=[^0-9]*[0-9])
- there must be at least one digit (after optional non-digits)
(?=(?:[^A-Za-z]*[A-Za-z]){2})
- there should be 2 ASCII letters (use \pL
to match Unicode letters and its counterclass \PL
to match characters other than Unicode letters)
(?=[^@#$%^&+=]*[@#$%^&+=])
- there must be at least 1 special symbol from the set
\\S{8,20}
- 8 to 20 non-whitespace symbols
$
- end of string
If any of the lookaheads return false, the whole match is failed. All of them are executed only once, right after the string start, before the first symbol.