skip to Main Content

I have the regex below

^(?=.*[A-Z])(?=.*[a-z])(?=.*d)(?=.*W)[A-Za-z0-9W][x00-x7F]{8,}$

am expecting from the regex the below

  • not less than 8 in length
  • at least one capital letter
  • at least one small letter
  • at least one digit
  • at least one non-alphanumeric symbol
  • all characters should be Latin only (no extended char like Ş in Turkish or special letters in German like Ü and no Arabic or such languages )

what am facing is the regex does match many strings, but, as a string like 123aB!ВЕ it’s not matching. Another example is the string June!12 It does not match either, but it could be matched if extended to be 9 letters in length June!12sd ???

for example, Fth4&yusÖ should not match because of the letter Ö but when removed it should match, but, it is not matching unless it’s extended to be more than 9 characters.

any help is appreciated

2

Answers


  1. It sounds like you’re just doing password validation, and regex is a tool you choose to use rather than a requirement. This sort of thing can be better (faster + easier to read) without regex.

    Here’s a C# solution without using regex.

    private static bool IsPasswordValid(string input)
    {
        if (input.Length < 8)
            return false;
    
        bool hasUppercaseLetter = false;
        bool hasLowercaseLetter = false;
        bool hasDigit = false;
        bool hasNonAlphaNumeric = false;
    
        foreach (var c in input)
        {
            // non-ASCII means immediate failure
            if (!char.IsAscii(c))
                return false;
    
            else if (char.IsAsciiDigit(c))
                hasDigit = true;
    
            else if (char.IsAsciiLetterUpper(c))
                hasUppercaseLetter = true;
    
            else if (char.IsAsciiLetterLower(c))
                hasLowercaseLetter = true;
    
            else if (c is '!' or '@' or '#' or '$' or '%' or '^' or '&' or '*') // add more as needed
                hasNonAlphaNumeric = true;
        }
    
        return hasUppercaseLetter && hasLowercaseLetter && hasDigit && hasNonAlphaNumeric;
    }
    

    This works by processing each character one by one and updating some booleans based on if it passes a rule or not. Because you don’t have any "max number of …" rules, simply setting the boolean to true every time you have a matching character is fine.

    It passes all your examples:

    • 123aB!ВЕ fails because the last two characters are Cyrillic.
    • 123aB!BE passes – this is an altered version of your example to make the last two characters use Latin letters.
    • June!12 fails as it less than 8 characters
    • June!12sd passes
    • Fth4&yusÖ fails because of the last character.
    Login or Signup to reply.
  2. This is a good way to do your specs.
    Note that white space is excluded as are other control codes.

    ^(?=[x21-x7e]{8,}$)(?=.*[W_])(?=.*[A-Z])(?=.*[a-z])(?=.*d).+$
    

    Explained

    ^ 
    (?= [x21-x7e]{8,} $ )       # ASCII only x21-x7e range 8 or more
    (?= .* [W_] )                # 1 Special Character 
    (?= .* [A-Z] )                # 1  A-Z Character
    (?= .* [a-z] )                # 1  a-z  Character
    (?= .* d )                   # 1  Digit Character
    .+                            # Passed get them all
    $ 
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search