I want to validate my password with eight characters or more and must contain at least two non-alphabetic (i.e., not A-Z) characters
You may use
s.matches("(?=(?:[^a-zA-Z]*[a-zA-Z]){2}).{8,}")
See the regex demo.
Another way of writing the same
s.matches("(?=.{8})(?:[^a-zA-Z]*[a-zA-Z]){2}.*")
Explanation
^
- (not necessary in .matches
as the method requires a full string match) - start of string
(?=
- start of a positive lookahead that requires, immediately to the right of the current location,
(?:[^a-zA-Z]*[a-zA-Z]){2}
- a non-capturing group that matches 2 consecutive occurrences of:
[^a-zA-Z]*
- any 0+ chars other than ASCII letters
[a-zA-Z]
- an ASCII letter
)
- end of the lookahead
.{8,}
- any 8 or more chars other than line break chars, as many as possible
$
- (not necessary in .matches
as the method requires a full string match) - end of string
In (?=.{8})(?:[^a-zA-Z]*[a-zA-Z]){2}.*
pattern, the first lookahead requires at least 8 chars, then at least two letters are requires using the (?:[^a-zA-Z]*[a-zA-Z]){2}
pattern, and then .*
matches the rest of the string.