Лучший способ написать этот RegEx? - PullRequest
0 голосов
/ 12 августа 2011

У меня есть этот пароль для регулярного выражения для приложения, цель которого:

Убедитесь, что пользователи используют от 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 ]

6 голосов
/ 12 августа 2011

Должно ли это быть регулярное выражение? Глядя на требования, все что вам нужно это String.Length и String.IndexOfAny().

3 голосов
/ 12 августа 2011

Во-первых, хорошая работа по предоставлению комментариев для вашего регулярного выражения. Тем не менее, есть гораздо лучший способ. Просто напишите свое регулярное выражение с самого начала в режиме свободного пробела с большим количеством комментариев. Таким образом, вы можете документировать свое регулярное выражение прямо в исходном коде (и предоставлять отступы для улучшения читабельности при большом количестве скобок). Вот как бы я написал ваше оригинальное регулярное выражение в коде 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.
} 

Это регулярное выражение исключает глобальную альтернативу и вместо этого использует группу без захвата для "цифр или спецсимволов" альтернативных утверждений. Кроме того, вы можете исключить группу без захвата для «специальных символов или пробелов» , просто добавив \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 голосов
/ 12 августа 2011

Я не уверен, имеет ли смысл то, что вы делаете, но для этого ваше регулярное выражение может быть проще

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

Зачем использовать альтернативы?Просто добавьте \d и \s к классу символов.

...