I can't figure out how to modify my regex to make sure the password follows the last condition:
- at least 2 capital letters in a row
- doesn't have space symbols
- contains digits
- doesn't contain 4 consecutive digits
{4} It currently disapproves the password if it has 4 and more digits but I need it to disapprove the password with EXACTLY 4 digits.
s1 = 'annII#443'
s2 = 'annII#4343'
s3 = 'annII#43434'
pattern = r"^(?=.*[A-Z]{2,})(?=.*[A-Za-z])(?=.*[0-9])(?!.*[0-9]{4})(?!.*[\s]).*$"
re.findall(pattern, s1) # ['aШnnII#443']
re.findall(pattern, s2) # []
re.findall(pattern, s3) # []
PS: It's just a task so don't worry. It's not gonna be used for any real purposes.
CodePudding user response:
- To match exactly four digits, you can use at start
^
e.g.(?!(?:.*\D)?\d{4}(?!\d))
.
This requires start or a\D
non-digit before the 4 digits and disallows a digit after. (?=.*[A-Za-z])
looks redundant if you already require(?=.*[A-Z]{2,})
(2 upper).{2,}
two or more is redundant.{2}
would suffice and does not change the logic.- Instead of
(?!.*[\s]).*$
you can just use\S*$
(upper matches non-whitespaces). - It's generally more efficient to use lazy
.*?
or even a negated class where possible.
^(?=[^A-Z]*[A-Z]{2})(?=\D*\d)(?!(?:.*\D)?\d{4}(?!\d))\S*$
See this demo at regex101 (added \n
to negations in multiline demo for staying in line)