Suwan  Wang
Suwan Wang

Reputation: 83

Password validator: password needs to contain EXACTLY one spacial character?

Task: Password validator
a. The length of the password needs to be from 8 to 30 characters.
b. The password needs to contain at least 2 uppercase characters.
c. The password needs to contain at least 2 lowercase characters.
d. The password needs to contain at least 1 digit.
e. The password needs to contain exactly 1, but not more of the following special characters:
@/%&*_-

This is my code:

special_character_set = "@/%&*_-"
is_valid = False
import re
while True:
    password = input("please enter a password: ")
    if len(password) > 30 or len(password)< 8:
        print("The length of the password needs to be from 8 to 30 characters!")
        continue
    elif re.search('[0-9]', password) is None:
        print("The password needs to contain at least 1 digit!")
        continue
    elif re.search ('[A-Z][A-Z]', password) is None:
        print("The password needs to contain at least 2 uppercase characters!")
        continue
    elif re.search('[a-z][a-z]', password) is None:
        print("The password needs to contain at least 2 lowercase characters!")
        continue
    elif re.search('[@/%&*_-]', password) is None:
        print("The password needs to contain one of the following special characters: @/%&*_-!")
        continue
    else:
        is_valid = True
    if is_valid:
        print("valid password")
        break

It works. However, the condition e) has not been completely fulfilled. How can I make the password contain ONLY ONE of the special characters?

Upvotes: 1

Views: 181

Answers (2)

Prune
Prune

Reputation: 77850

Don't use regex for this; add up the counts of special characters in the proposed password:

>>> passwd = "My_Pass@"
>>> special = '[@/%&*_-]'
>>> special_count = sum(passwd.count(c) for c in special)
>>> special_count
2

You can now use special_count as desired.

Upvotes: 1

jedwards
jedwards

Reputation: 30230

What about len + re.findall():

...
elif len(re.findall('[@/%&*_-]', password)) != 1:
    # Some number of special characters other than 1 was found
    ...

or

...
elif len(re.findall('[@/%&*_-]', password)) == 0:
    # No special characters were found
    ...
elif len(re.findall('[@/%&*_-]', password)) > 1:
    # Too many special characters were found

(and if you do the latter, try not to run the regex twice)

Upvotes: 1

Related Questions