写这个RegEx的更好方法是什么?

时间:2011-08-12 08:50:40

标签: c# .net regex passwords

我有一个正在构建的应用程序的密码正则表达式,其目的是:

确保用户使用6到12个字符。

确保用户使用一个特殊字符或一个数字。

此外,它不区分大小写。

应用程序在.net中我有以下正则表达式:

I have the following regex for the password checker, bit lengthy but for your viewing if you feel any of this is wrong please let me know.

^(?=.*\d)(?=.*[A-Za-z]).{6-12}$|^(?=.*[A-Za-z])(?=.*[!#$%&'\(\)\*\+-\.:;<=>\?@\[\\\]\^_`\{\|\}~0x0022]|.*\s).{6,12}$

正好打破正则表达式,确保你们都高兴它是正确的。

^ = start of string ”^” 

(?=.*\d) = must contain “?=” any set of characters “.*” but must include a digit “\d”.

(?=.*[A-Za-z]) = must contain “?=” any set of characters “.*” but must include an insensitive case letter.

.{6-12}$ = must contain any set of characters “.” but must have between 6-12 characters and end of string “$”.

|^ = or “|” start of string “^”

(?=.*[A-Za-z]) = must contain “?=” any set of characters “.*” but must include an insensitive case letter.

(?=.*[!#$%&'\(\)\*\+-\.:;<=>\?@\[\\\]\^_`\{\|\}~0x0022]|.*\s)  = must contain “?=” any set of characters “.*” but must include at least special character we have defined or a space ”|.*\s)”. “0x0022” is Unicode for single quote “ character. 

.{6,12}$ = set of characters “.” must be between 6 – 12 and this is the end of the string “$”

这是漫长的啰嗦,似乎正在做这项工作,但我想知道是否有更简单的方法来编写这种正则表达式,我想知道如果可能的话我如何缩短它?

感谢高级。

3 个答案:

答案 0 :(得分:6)

它必须是正则表达式吗?查看要求,您只需String.LengthString.IndexOfAny()

答案 1 :(得分:3)

首先,好好为你的正则表达式提供评论。但是,有一个更好的方法。只需在自由间隔模式下从一开始就编写正则表达式,并附带大量注释。这样,您就可以在源代码中记录正则表达式(并在有大量括号时提供缩进以提高可读性)。以下是我用C#代码编写原始正则表达式的方法:

if (Regex.IsMatch(usernameString, 
    @"# Validate username having a digit and/or special char.
      ^               # Either... Anchor to start of string.
      (?=.*\d)        # Assert there is a digit AND
      (?=.*[A-Za-z])  # assert there is an alpha.
      .{6-12}         # Match any name with length from 6 to 12.
      $               # Anchor to end of string.
    | ^               # Or... Anchor to start of string
      (?=.*[A-Za-z])  # Assert there is an alpha AND
      (?=.*           # assert there is either a special char
        [!#$%&'\(\)\*\+-\.:;<=>\?@\[\\\]\^_`\{\|\}~\x22]
      | .*\s          # or a space char.
      )               # End specialchar-or-space assertion.
      .{6-12}         # Match any name with length from 6 to 12.
      $               # Anchor to end of string.
    ", RegexOptions.IgnorePatternWhitespace)) {
    // Valid username.
} else {
    // Invalid username.
} 

上面的代码段使用了首选的@"..."字符串语法,简化了元字符的转义。这个原始正则表达式错误地使用破折号分隔大括号量词的两个数字,即.{6-12}。正确的语法是用逗号分隔这些数字,即.*{6,12}。 (也许.NET允许使用.{6-12}语法?)我还将0x0022"双引号字符)更改为\x22

那就是说,原来的正则表达式可以改进一下:

if (Regex.IsMatch(usernameString, 
    @"# Validate username having a digit and/or special char.
    ^                # Anchor to start of string.
    (?=.*?[A-Za-z])  # Assert there is an alpha.
    (?:              # Group for assertion alternatives.
      (?=.*?\d)      # Either assert there is a digit
    |                # or assert there is a special char
      (?=.*?[!#$%&'()*+-.:;<=>?@[\\\]^_`{|}~\x22\s])  # or space.
    )                # End group of assertion alternatives.
      .{6,12}        # Match any name with length from 6 to 12.
    $                # Anchor to end of string.
    ", RegexOptions.IgnorePatternWhitespace)) {
    // Valid username.
} else {
    // Invalid username.
} 

此正则表达式消除了全局替代方案,而是使用非捕获组来表示“digit或specialchar”断言替代方案。此外,您可以通过简单地将\s添加到特殊字符列表中来消除“特殊字符或空格”备选方案的非捕获组。我还为断言中的点星添加了一个惰性修饰符,即.*? - (这可能使正则表达式匹配更快一些。)从specialchar字符类中删除了一堆不必要的转义符。

但正如Stema巧妙地指出的那样,你可以将数字和特殊字符组合起来进一步简化:

if (Regex.IsMatch(usernameString, 
    @"# Validate username having a digit and/or special char.
    ^                # Anchor to start of string
    (?=.*?[A-Za-z])  # Assert there is an alpha.
                     # Assert there is a special char, space
    (?=.*?[!#$%&'()*+-.:;<=>?@[\\\]^_`{|}~\x22\s\d])  # or digit.
    .{6,12}          # Match any name with length from 6 to 12.
    $                # Anchor to end of string.
    ", RegexOptions.IgnorePatternWhitespace)) {
    // Valid username.
} else {
    // Invalid username.
} 

除此之外,您的原始正则表达式在准确性方面确实没有任何问题。但是,从逻辑上讲,这个公式允许用户名以空格结尾,这可能不是一个好主意。我还会在名称中明确指定允许字符的白名单,而不是使用过度宽容的"."点。

答案 2 :(得分:2)

我不确定你的行为是否合理,但要实现这一点,你的正则表达式可以更简单

^(?=.*[A-Za-z])(?=.*[\d\s!#$%&'\(\)\*\+-\.:;<=>\?@\[\\\]\^_`\{\|\}~0x0022]).{6,12}$

为何使用替代品?只需将\d\s添加到角色类。