ChatGPT解决这个技术问题 Extra ChatGPT

Regular expression to check if password is "8 characters including 1 uppercase letter, 1 special character, alphanumeric characters"

I want a regular expression to check that

a password must be eight characters including one uppercase letter, one special character and alphanumeric characters.

And here is my validation expression which is for eight characters including one uppercase letter, one lowercase letter, and one number or special character.

(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$"

How I can write it for a password that must be eight characters including one uppercase letter, one special character and alphanumeric characters?

Why do you need a regular expression for this? A complete regular expression matching your requirements will be very long and complex. It's easier to write your constraints in C# code.
Have you considered checking for a strong password, rather than checking that the password meets some arbitrary rules which are an imperfect proxy for a strong password? There are plenty of libraries and programs which, when fed a password, will determine its strength.
@GregHewgill I would upvote your comment if I could :-) This looks like another case of "if all you have is a hammer, everything starts to look like a nail".
Do you need exactly one uppercase/special character or at least one?
By user's requirement, do you mean your user is dictating implementation detail? Perhaps they should just code this themselves, then. To be honest, I think it would be easier to maintain and understand if you just created counters and checked every character one by one, incrementing the appropriate counters for every character that matches a rule. From a technical standpoint it's not something that will impress anyone, but why complicate things with something that will be error-prone and hard to update?

n
npinti

The regular expression you are after will most likely be huge and a nightmare to maintain especially for people who are not that familiar with regular expressions.

I think it would be easier to break your regex down and do it one bit at a time. It might take a bit more to do, but I am pretty sure that maintaining it and debugging it would be easier. This would also allow you to provide more directed error messages to your users (other than just Invalid Password) which should improve user experience.

From what I am seeing you are pretty fluent in regex, so I would presume that giving you the regular expressions to do what you need would be futile.

Seeing your comment, this is how I would go about it:

Must be eight characters Long: You do not need a regex for this. Using the .Length property should be enough.

Including one uppercase letter: You can use the [A-Z]+ regular expression. If the string contains at least one upper case letter, this regular expression will yield true.

One special character: You can use either the \W which will match any character which is not a letter or a number or else, you can use something like so [!@#] to specify a custom list of special characters. Note though that characters such as $, ^, ( and ) are special characters in the regular expression language, so they need to be escaped like so: \$. So in short, you might use the \W.

Alphanumeric characters: Using the \w+ should match any letter and number and underscore.

Take a look at this tutorial for more information.


i have not written this my self i get it from google dear friend
@RaniaUmair: I think that your comment proves my point. I would recommend that you break it down like I have specified.
+1 Regex is powerful, but wasn't meant to solve any problem in the universe
Too late for a response; but this method also allows to tell the user exactly where they went wrong.. Where a regex containing it all will only be able to say what the requirements are.. Breaking it down into multiple "if's" will let you tell the user: "Oooh wait, you need to have at least one symbol" and such.. Way more user friendly.
Wouldn't it be sufficient to check [A-Z] (without the +) here? Since you're just checking that at least one exists in the password, you only need to match one (not however many in a row there are).
m
mmdemirbas
(                   # Start of group
    (?=.*\d)        #   must contain at least one digit
    (?=.*[A-Z])     #   must contain at least one uppercase character
    (?=.*\W)        #   must contain at least one special symbol
       .            #     match anything with previous condition checking
         {8,8}      #        length is exactly 8 characters
)                   # End of group

In one line:

((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})

Edit 2019-05-28:

You need to match entire input string. So, you can enclose the regex between ^ and $ to prevent accidentally assuming partial matches as matching entire input:

^((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})$

Sources:

Password matching expression

Password Strength Validation with Regular Expressions


Because it consists of 12 characters
one more condition should not start with a digit how can i do this?
You can shorten it using {8} instead to match 8 characters
its matching for $1eerrrrrrr.. its has no uppercase letter.
@ShilpiJaiswal Either you are using a flag for case-insensitive match, or making a "find" instead of "match". To ensure you are matching entire input string, you can enclose the regex between ^ and $. Try this: ^((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})$
M
Matt Timmermans

So many answers.... all bad!

Regular expressions don't have an AND operator, so it's pretty hard to write a regex that matches valid passwords, when validity is defined by something AND something else AND something else...

But, regular expressions do have an OR operator, so just apply DeMorgan's theorem, and write a regex that matches invalid passwords.

anything with less than 8 characters OR anything with no numbers OR anything with no uppercase OR anything with no special characters

So:

^(.{0,7}|[^0-9]*|[^A-Z]*|[a-zA-Z0-9]*)$

If anything matches that, then it's an invalid password.


If the OP wanted exactly 8 characters, so you'd need to add |.{9,}. +1 for the concept
Great and simple solution for the question, although I agree a single regular expression is not the optimal one for the actual problem.
Regular expressions do have AND operators, they're called lookahead/lookbehind assertions.
P
Preston L. Bannister

The answer is to not use a regular expression. This is sets and counting.

Regular expressions are about order.

In your life as a programmer you will asked to do many things that do not make sense. Learn to dig a level deeper. Learn when the question is wrong.

The question (if it mentioned regular expressions) is wrong.

Pseudocode (been switching between too many languages, of late):

if s.length < 8:
    return False
nUpper = nLower = nAlphanum = nSpecial = 0
for c in s:
    if isUpper(c):
        nUpper++
    if isLower(c):
        nLower++
    if isAlphanumeric(c):
        nAlphanum++
    if isSpecial(c):
        nSpecial++
return (0 < nUpper) and (0 < nAlphanum) and (0 < nSpecial)

Bet you read and understood the above code almost instantly. Bet you took much longer with the regex, and are less certain it is correct. Extending the regex is risky. Extended the immediate above, much less so.

Note also the question is imprecisely phrased. Is the character set ASCII or Unicode, or ?? My guess from reading the question is that at least one lowercase character is assumed. So I think the assumed last rule should be:

return (0 < nUpper) and (0 < nLower) and (0 < nAlphanum) and (0 < nSpecial)

(Changing hats to security-focused, this is a really annoying/not useful rule.)

Learning to know when the question is wrong is massively more important than clever answers. A clever answer to the wrong question is almost always wrong.


I agree. The more people you work with, the more code needs to be readable although some regexp implementation I saw as answers are quite clear
I like that some users like you have courage to say that Regex is not always better solution to apply and that sometime, simple programming is more readable.
s
stema

As an example how this could be done with a readable/maintainable regex.

For a longer regex you should always use RegexOptions.IgnorePatternWhitespace to allow whitespace and comments in the expression for better readability.

String[] passwords = { "foobar", "Foobar", "Foobar1", "Fooobar12" };

foreach (String s in passwords) {

    Match password = Regex.Match(s, @"
                                      ^              # Match the start of the string
                                       (?=.*\p{Lu})  # Positive lookahead assertion, is true when there is an uppercase letter
                                       (?=.*\P{L})   # Positive lookahead assertion, is true when there is a non-letter
                                       \S{8,}        # At least 8 non whitespace characters
                                      $              # Match the end of the string
                                     ", RegexOptions.IgnorePatternWhitespace);

    if (password.Success) {
        Console.WriteLine(s + ": valid");
    }
    else {
        Console.WriteLine(s + ": invalid");
    }
}

Console.ReadLine();

This is the best way to abuse the lookahead assertion as kind of an "and" pattern to cover the whole constraint within a single regex. Works for more constraints and can easily be generated if some constraints should be enabled/disabled by configuration.
The use of Unicode categories is an excellent idea. The world is wider than ASCII!
u
user1096188

If you need only one upper case and special character then this should work:

@"^(?=.{8,}$)(?=[^A-Z]*[A-Z][^A-Z]*$)\w*\W\w*$"

The string AAaaaaaaa# is not OK according to this expression
Well, it is 10, not 8 characters long and contains more than one upper case latter, so it should fail...
You are right, it does say this in the question. I thought these rules were more like "at least one uppercase" instead of "exactly one uppercase". I'm not sure it that's what the OP wanted though.
L
Lucas Silva

The regular expression you was looking for is: /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*\[\]"\';:_\-<>\., =\+\/\\]).{8,}$/u.

Example and test: http://regexr.com/3fhr4


Spaces are allowed
@sniels Just change the . before the {8,} to [^\s].
C
Community

This question starts to be viral and a lot of interesting suggestion appeared.

Yes, writing by hand is difficult. So an easier solution is to use a template. Although the resulted regex may not be most optimal, it will be easier to maintain and/or change, and the user will have a better control over the result. It is possible that I missed something, so any constructive criticism will be helpful.

This links might be interesting: match at least 2 digits 2 letters in any order in a string, Regular Expression Language, Capturing groups

I'm using this template (?=(?:.*?({type})){({count})}) based on all of the regex I saw in SO. The next step is replacing the needed pattern ( number, special character ... ) and adding configuration for length.

I've made a little class for composing the regex PasswordRegexGenerator.cs An example:

string result = new PasswordRegexGenerator ( )
        .UpperCase ( 3, -1 )    // ... {3,}
        .Number ( 2, 4 )        // ... {2,4}
        .SpecialCharacter ( 2 ) // ... {2}
        .Total ( 8,-1 )
        .Compose ( );

/// <summary>
/// Generator for regular expression, validating password requirements.
/// </summary>
public class PasswordRegexGenerator
{
    private string _elementTemplate = "(?=(?:.*?({type})){({count})})";

    private Dictionary<string, string> _elements = new Dictionary<string, string> {
        { "uppercase", "[A-Z]" },
        { "lowercase", "[a-z]" },
        { "number", @"\d" },
        { "special", @"\W" },
        { "alphanumeric", @"\w" }
    };

    private StringBuilder _sb = new StringBuilder ( );

    private string Construct ( string what, int min, int max )
    {
        StringBuilder sb = new StringBuilder ( _elementTemplate );
        string count = min.ToString ( );

        if ( max == -1 )
        {
            count += ",";
        }
        else if ( max > 0 )
        {
            count += "," + max.ToString();
        }

        return sb
            .Replace ( "({type})", what )
            .Replace ( "({count})", count )
            .ToString ( );
    }

    /// <summary>
    /// Change the template for the generation of the regex parts
    /// </summary>
    /// <param name="newTemplate">the new template</param>
    /// <returns></returns>
    public PasswordRegexGenerator ChangeRegexTemplate ( string newTemplate )
    {
        _elementTemplate = newTemplate;
        return this;
       }

    /// <summary>
    /// Change or update the regex for a certain type ( number, uppercase ... )
    /// </summary>
    /// <param name="name">type of the regex</param>
    /// <param name="regex">new value for the regex</param>
    /// <returns></returns>
    public PasswordRegexGenerator ChangeRegexElements ( string name, string regex )
    {
        if ( _elements.ContainsKey ( name ) )
        {
            _elements[ name ] = regex;
        }
        else
        {
            _elements.Add ( name, regex );
        }
        return this;
    }

    #region construction methods 

    /// <summary>
    /// Adding number requirement
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public PasswordRegexGenerator Number ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "number" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator UpperCase ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "uppercase" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator LowerCase ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "lowercase" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator SpecialCharacter ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "special" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator Total ( int min, int max = 0 )
    {
        string count = min.ToString ( ) + ( ( max == 0 ) ? "" : "," + max.ToString ( ) );
        _sb.Append ( ".{" + count + "}" );
        return this;
    }

    #endregion

    public string Compose ()
    {
        return "(" + _sb.ToString ( ) + ")";
    }
}

a
amit pandya

You can use below class for validation:

public class PasswordValidator{

  private Pattern pattern;
  private Matcher matcher;

  private static final String PASSWORD_PATTERN =
          "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{6,20})";

  public PasswordValidator(){
      pattern = Pattern.compile(PASSWORD_PATTERN);
  }

  /**
   * Validate password with regular expression
   * @param password password for validation
   * @return true valid password, false invalid password
   */
  public boolean validate(final String password){

      matcher = pattern.matcher(password);
      return matcher.matches();

  }
}

where 6 and 20 are minimum and maximum length for the password.


r
relatively_random

Use a nonbacktracking expression to match the whole password first, if it has at least 8 characters (this way, there is no combinatorial explosion for long, but invalid passwords): (?>{8,})

Use lookbehind assertions to check for presence of all required characters (AND-conditions). (?<=...)

At least one uppercase character: (?<=\p{Lu}.*)

At least one special character (a bit ambiguous, but let's use not-word): (?<=\W.*)

At least one alphanumeric character (: (?<=\w.*)

Summed up:

(?>.{8,})(?<=\p{Lu}.*)(?<=\W.*)(?<=\w.*)


A
ANSerpen

Best is not using regex for everything. Those requirements are very light. On CPU-wise string operations for checking the criteria/validation is much cheaper and faster than regex!


P
Pyke Kaisora

The one I found for a minimum of 8 characters, consist of at least 1 lowercase and 1 uppercase and 1 number and 1 symbols.

^((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,})$

B
Brian Tompsett - 汤莱恩

var regex =/^(?=.*\d)(?=.*[!@#$%^&*])(?=.*[a-z])(?=.*[A-Z]).{8,64}$/; function test() { if(regex.test(document.getElementById("txtPassword").value)===false) { alert("Min 6,Max 64,At Least One Uppercase Character,One Lowercase Character,One Numeric Value And One Special Character(!@#$%^&*) Required "); } else { alert("Success"); } }


While this code snippet may solve the problem, it doesn't explain why or how it answers the question. Please include an explanation for your code, as that really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. You can use the edit button to improve this answer to get more votes and reputation!
N
Nikolay Kostov
/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$/

I suggest you edit your question and include some explanation. Code-only answers are sometimes good enough, but code + explanation answers are always better