You can use
^(?=[^A-Z]*[A-Z][^A-Z]*$)(?=[^a-z]*[a-z][^a-z]*$)(?=(?:D*d){6}D*$)[a-zA-Z0-9]{8}$
See the regex demo (a bit modified due to the multiline input). In Java, do not forget to use double backslashes (e.g. \d
to match a digit).
Here is a breakdown:
^
- start of string (assuming no multiline flag is to be used)
(?=[^A-Z]*[A-Z][^A-Z]*$)
- check if there is only 1 uppercase letter (use p{Lu}
to match any Unicode uppercase letter and P{Lu}
to match any character other than that)
(?=[^a-z]*[a-z][^a-z]*$)
- similar check if there is only 1 lowercase letter (alternatively, use p{Ll}
and P{Ll}
to match Unicode letters)
(?=(?:D*d){6}D*$)
- check if there are six digits in a string (=from the beginning of the string, there can be 0 or more non-digit symbols (D
matches any character but a digit, you may also replace it with [^0-9]
), then followed by a digit (d
) and then followed by 0 or more non-digit characters (D*
) up to the end of string ($
)) and then
[a-zA-Z0-9]{8}
- match exactly 8 alphanumeric characters.
$
- end of string.
Following the logic, we can even reduce this to just
^(?=[^a-z]*[a-z][^a-z]*$)(?=(?:D*d){6}D*$)[a-zA-Z0-9]{8}$
One condition can be removed as we only allow lower- and uppercase letters and digits with [a-zA-Z0-9]
, and when we apply 2 conditions the 3rd one is automatically performed when matching the string (one character must be an uppercase in this case).
When using it with Java matches()
method, there is no need to use ^
and $
anchors at the start and end of the pattern, but you still need it in the lookaheads:
String s = "K82v6686";
String rx = "(?=[^a-z]*[a-z][^a-z]*$)" + // 1 lowercase letter check
"(?=(?:\D*\d){6}\D*$)" + // 6 digits check
"[a-zA-Z0-9]{8}"; // matching 8 alphanum chars exactly
if (s.matches(rx)) {
System.out.println("Valid");
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…