Home > Blockchain >  Regex Python with min a letter, a number and min a non-alphanumeric character
Regex Python with min a letter, a number and min a non-alphanumeric character

Time:12-06

I would like to check if a string contains at least: 12 characters, min a letter, min a number and finally min a non-alphanumeric character. I am in the process of creating a Regex but it does not meet my expectations.

Here is the Regex:

regex = re.compile('([A-Za-z] [0-9] \W ){12,}')


def is_valid(string):
    return re.fullmatch(regex, string) is not None


test_string = "abdfjhfl58425!!"
print(is_valid(test_string))

When the string contains numbers after letters, it does not match!

Could you help me? Thank you.

CodePudding user response:

Your regex is wrong. I found this on another post which describes a different scenario albeit very similar.

You can tweak this regex so that it reads like this:

^(.{0,12}|[^a-zA-Z]{1,}|[^\d]{1,}|[^\W]{1,})$|[\s]

Now what you have here is a regex that matches only when the password is invalid. Meaning that if you have no matches, the password is valid, and if you have matches the password is invalid. So you will need to alter the code to suit but try that regex above instead and it should work for all combinations.

The final working code would then be (with extra tests):

import re

regex = re.compile('^(.{0,12}|[^a-zA-Z]{1,}|[^\d]{1,}|[^\W]{1,})$|[\s]')


def is_valid(string):
    return re.fullmatch(regex, string) is None


test_string = "abdfl58425B!!"
print(is_valid(test_string))

test_string = "ABRER58425B!!"
print(is_valid(test_string))

test_string = "eruaso58425!!"
print(is_valid(test_string))

CodePudding user response:

Regex is not really suited to this task as it involves remembering counts of each type of character. You could construct a regex to do it but it would end up being very long and unreadable. Much simpler to write a function to count the number of occurrences of each type of character, something like:

def is_valid(test_string):
    if len(test_string) >= 12 \
    and len([c for c in test_string if c.isalpha()]) >= 1 \
    and len([c for c in test_string if c.isnumeric()]) >= 1 \
    and len([c for c in test_string if not c.isalnum()]) >= 1:
        return True
    else:
        return False

CodePudding user response:

If that helps: if you want to do the same thing but without ReGex, you can use this function that I had done! It works perfectly!

def is_strong_password(a_string):
    if len(a_string) >= 12:
        chiffre = 0
        lettre = 0
        alnum = 0
        for x in a_string:
            if x.isalpha():
                lettre  = 1
            if x.isdigit():
                chiffre  = 1
            if not x.isalnum():
                alnum  = 1
        if lettre > 1 and chiffre > 1 and alnum > 1:
            return True
        else:
            return False
    else:
        return False
  • Related