Есть ли более лаконичное регулярное выражение для выполнения этой задачи? - PullRequest
5 голосов
/ 28 мая 2010

Прежде всего, извините за хромое название, но я не мог придумать лучшего. Мне нужно проверить пароль, чтобы убедиться в следующем:

Пароли должны содержать не менее 3 из следующих элементов:

  • заглавные буквы
  • строчные буквы
  • номер
  • специальные символы

Вот что я придумал (это работает, но мне интересно, есть ли лучший способ сделать это):

    Dim lowerCase As New Regex("[a-z]")
    Dim upperCase As New Regex("[A-Z]")
    Dim numbers As New Regex("\d")
    Dim special As New Regex("[\\\.\+\*\?\^\$\[\]\(\)\|\{\}\/\'\#]")

    Dim count As Int16 = 0

    If Not lowerCase.IsMatch(txtUpdatepass.Text) Then
        count += 1
    End If
    If Not upperCase.IsMatch(txtUpdatepass.Text) Then
        count += 1
    End If
    If Not numbers.IsMatch(txtUpdatepass.Text) Then
        count += 1
    End If
    If Not special.IsMatch(txtUpdatepass.Text) Then
        count += 1
    End If

Если хотя бы 3 критерия не были выполнены, я справляюсь с этим. Я не очень разбираюсь в регулярных выражениях и читаю многочисленные учебники в Интернете. Есть ли способ объединить все 4 регулярных выражения в одно? Но я полагаю, что это не позволило бы мне проверить, выполнены ли хотя бы 3 критерия.

Кстати, есть ли у сайта исчерпывающий список всех символов, которые необходимо экранировать в регулярном выражении (те, которые имеют особое значение - например, $, ^ и т. Д.)?

Как всегда, TIA. Я не могу выразить достаточно, насколько классным я считаю этот сайт.

Ответы [ 6 ]

6 голосов
/ 28 мая 2010

То, как у вас это получается, настолько хорошо, насколько это возможно. Вы могли бы сделать все это в одной строке, но это было бы ужасно запутано и не помогло бы вообще.

Подумайте о том, что вы пытаетесь сделать; Вы хотите проверить по четырем различным критериям. Поскольку каждый критерий - это, по сути, одно сравнение, вам нужно проверить каждый критерий в отдельности, что вы и делаете.

3 голосов
/ 28 мая 2010

Я думаю, что ваш подход здесь разумный. Понятно, чего именно вы пытаетесь достичь (так, чтобы не было правильного регулярного выражения), и это работает!

Большинство языков имеют очень хорошую документацию по обработке своих регулярных выражений, поэтому я бы посоветовал сначала посмотреть там. В противном случае я нахожу документацию регулярного выражения JavaScript *1003* * очень хорошей для подмножества регулярных выражений, поддерживаемых этим языком (который охватывает наиболее реалистичное использование).

Еще один совет - вам не нужно экранировать все эти специальные символы, когда вы находитесь внутри набора символов (квадратные скобки). «[{} [.? * ^ $ |]» совершенно правильно. (Вам, очевидно, нужно бежать] и ваши разделители (").

2 голосов
/ 28 мая 2010

Я верю, что это работает, но это просто показывает, насколько ужасно это будет. Вы не получите ни скорости, ни читабельности.

Try
    If Regex.IsMatch(SubjectString, "(?=\S*?[a-z])(?=\S*?[0-9])(?=\S*?[\\.+*?\^$[\]()|{}/'#])\S{3,}|(?=\S*?[A-Z])(?=\S*?[0-9])(?=\S*?[\\.+*?\^$[\]()|{}/'#])\S{3,}|(?=\S*?[A-Z])(?=\S*?[a-z])(?=\S*?[\\.+*?\^$[\]()|{}/'#])\S{3,}|(?=\S*?[A-Z])(?=\S*?[a-z])(?=\S*?[0-9])\S{3,}") Then
        ' Successful match
    Else
        ' Match attempt failed
    End If
Catch ex As ArgumentException
    'Syntax error in the regular expression
End Try

Regexbuddy объяснение

' (?=\S*?[a-z])(?=\S*?[0-9])(?=\S*?[\\\.\+\*\?\^\$\[\]\(\)\|\{\}\/\'\#])\S{3,}|(?=\S*?[A-Z])(?=\S*?[0-9])(?=\S*?[\\\.\+\*\?\^\$\[\]\(\)\|\{\}\/\'\#])\S{3,}|(?=\S*?[A-Z])(?=\S*?[a-z])(?=\S*?[\\\.\+\*\?\^\$\[\]\(\)\|\{\}\/\'\#])\S{3,}|(?=\S*?[A-Z])(?=\S*?[a-z])(?=\S*?[0-9])\S{3,}
' 
' Match either the regular expression below (attempting the next alternative only if this one fails) «(?=\S*?[a-z])(?=\S*?[0-9])(?=\S*?[\\\.\+\*\?\^\$\[\]\(\)\|\{\}\/\'\#])\S{3,}»
'    Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=\S*?[a-z])»
'       Match a single character that is a “non-whitespace character” «\S*?»
'          Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
'       Match a single character in the range between “a” and “z” «[a-z]»
'    Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=\S*?[0-9])»
'       Match a single character that is a “non-whitespace character” «\S*?»
'          Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
'       Match a single character in the range between “0” and “9” «[0-9]»
'    Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=\S*?[\\\.\+\*\?\^\$\[\]\(\)\|\{\}\/\'\#])»
'       Match a single character that is a “non-whitespace character” «\S*?»
'          Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
'       Match a single character present in the list below «[\\\.\+\*\?\^\$\[\]\(\)\|\{\}\/\'\#]»
'          A \ character «\\»
'          A . character «\.»
'          A + character «\+»
'          A * character «\*»
'          A ? character «\?»
'          A ^ character «\^»
'          A $ character «\$»
'          A [ character «\[»
'          A ] character «\]»
'          A ( character «\(»
'          A ) character «\)»
'          A | character «\|»
'          A { character «\{»
'          A } character «\}»
'          A / character «\/»
'          A ' character «\'»
'          A # character «\#»
'    Match a single character that is a “non-whitespace character” «\S{3,}»
'       Between 3 and unlimited times, as many times as possible, giving back as needed (greedy) «{3,}»
' Or match regular expression number 2 below (attempting the next alternative only if this one fails) «(?=\S*?[A-Z])(?=\S*?[0-9])(?=\S*?[\\\.\+\*\?\^\$\[\]\(\)\|\{\}\/\'\#])\S{3,}»
'    Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=\S*?[A-Z])»
'       Match a single character that is a “non-whitespace character” «\S*?»
'          Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
'       Match a single character in the range between “A” and “Z” «[A-Z]»
'    Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=\S*?[0-9])»
'       Match a single character that is a “non-whitespace character” «\S*?»
'          Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
'       Match a single character in the range between “0” and “9” «[0-9]»
'    Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=\S*?[\\\.\+\*\?\^\$\[\]\(\)\|\{\}\/\'\#])»
'       Match a single character that is a “non-whitespace character” «\S*?»
'          Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
'       Match a single character present in the list below «[\\\.\+\*\?\^\$\[\]\(\)\|\{\}\/\'\#]»
'          A \ character «\\»
'          A . character «\.»
'          A + character «\+»
'          A * character «\*»
'          A ? character «\?»
'          A ^ character «\^»
'          A $ character «\$»
'          A [ character «\[»
'          A ] character «\]»
'          A ( character «\(»
'          A ) character «\)»
'          A | character «\|»
'          A { character «\{»
'          A } character «\}»
'          A / character «\/»
'          A ' character «\'»
'          A # character «\#»
'    Match a single character that is a “non-whitespace character” «\S{3,}»
'       Between 3 and unlimited times, as many times as possible, giving back as needed (greedy) «{3,}»
' Or match regular expression number 3 below (attempting the next alternative only if this one fails) «(?=\S*?[A-Z])(?=\S*?[a-z])(?=\S*?[\\\.\+\*\?\^\$\[\]\(\)\|\{\}\/\'\#])\S{3,}»
'    Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=\S*?[A-Z])»
'       Match a single character that is a “non-whitespace character” «\S*?»
'          Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
'       Match a single character in the range between “A” and “Z” «[A-Z]»
'    Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=\S*?[a-z])»
'       Match a single character that is a “non-whitespace character” «\S*?»
'          Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
'       Match a single character in the range between “a” and “z” «[a-z]»
'    Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=\S*?[\\\.\+\*\?\^\$\[\]\(\)\|\{\}\/\'\#])»
'       Match a single character that is a “non-whitespace character” «\S*?»
'          Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
'       Match a single character present in the list below «[\\\.\+\*\?\^\$\[\]\(\)\|\{\}\/\'\#]»
'          A \ character «\\»
'          A . character «\.»
'          A + character «\+»
'          A * character «\*»
'          A ? character «\?»
'          A ^ character «\^»
'          A $ character «\$»
'          A [ character «\[»
'          A ] character «\]»
'          A ( character «\(»
'          A ) character «\)»
'          A | character «\|»
'          A { character «\{»
'          A } character «\}»
'          A / character «\/»
'          A ' character «\'»
'          A # character «\#»
'    Match a single character that is a “non-whitespace character” «\S{3,}»
'       Between 3 and unlimited times, as many times as possible, giving back as needed (greedy) «{3,}»
' Or match regular expression number 4 below (the entire match attempt fails if this one fails to match) «(?=\S*?[A-Z])(?=\S*?[a-z])(?=\S*?[0-9])\S{3,}»
'    Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=\S*?[A-Z])»
'       Match a single character that is a “non-whitespace character” «\S*?»
'          Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
'       Match a single character in the range between “A” and “Z” «[A-Z]»
'    Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=\S*?[a-z])»
'       Match a single character that is a “non-whitespace character” «\S*?»
'          Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
'       Match a single character in the range between “a” and “z” «[a-z]»
'    Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=\S*?[0-9])»
'       Match a single character that is a “non-whitespace character” «\S*?»
'          Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
'       Match a single character in the range between “0” and “9” «[0-9]»
'    Match a single character that is a “non-whitespace character” «\S{3,}»
'       Between 3 and unlimited times, as many times as possible, giving back as needed (greedy) «{3,}»
1 голос
/ 28 мая 2010

Есть ли способ объединить все 4 регулярных выражения в одно? Но я полагаю, что это не позволило бы мне проверить, выполнены ли хотя бы 3 критерия.

Это неприятная часть: «3 из 4», которую трудно перевести в (одно) регулярное выражение. То, как вы справляетесь с этим сейчас, прекрасно, ИМО.

Кстати, есть ли у сайта исчерпывающий список всех символов, которые необходимо экранировать в регулярном выражении (те, которые имеют особое значение - например, $, ^ и т. Д.)?

Специальные символы Regex могут незначительно отличаться от реализации к реализации. Но, как правило, они особенные, и поэтому их следует избегать:

.    // match any character (often not line breaks)
\    // used to escape characters
*    // quantifier: zero or more
+    // quantifier: one or more
?    // quantifier: once or none
(    // start of a group
)    // end of a group
[    // start of a character class
{    // start of a quantifier like X{2,5} (match 'X' between 2 and 5 times)
^    // start of the input string (or line)
$    // end of the input string (or line)
|    // OR

Обратите внимание, что внутри класса персонажей большинство вышеперечисленных персонажей теряют свои "специальные способности". Класс символов можно рассматривать как маленький язык внутри языка регулярных выражений. У него есть свои специальные символы:

^    // when placed at the very start of the character class, it negates the class
-    // when NOT placed at the start or end of the class, it denotes a range: [a-c] matches 'a', 'b' or 'c'
\    // used to escape characters
]    // end of a character class


Некоторые примеры:

Если вы хотите сопоставить литерал ^ внутри класса символов, вам нужно либо экранировать его в самом начале, либо не размещать его в начале:

[\^a]    // matches either 'a' or '^'
[a^]     // matches either '^' or 'a'

Более специальные символы класса персонажей:

[a[\]b]    // matches either 'a', '[', ']' or 'b'

Диапазон - символов в действии:

[a-c]     // matches 'a', 'b' or 'c'
[ac-]     // matches 'a', 'c' or '-'
[-ac]     // matches '-', 'a' or 'c'
[a\-c]    // matches 'a', '-' or 'c'

Так что этим не нужно убегать:

[.()]    // simply matches either '.', '(' or ')'
0 голосов
/ 28 мая 2010

Просто для удовольствия, вот изящный способ выполнить работу в одном регулярном выражении:

"^(?=(?:.*[a-z]())?)(?=.*[A-Z]()|\1)(?=.*[0-9]()|\1\2)(?=\1\2\3|.*[.+*?^$\[\]()|{}/'#\\])[a-zA-Z0-9.+*?^$\[\]()|{}/'#\\]+$"

Здесь используется трюк, который был популярен у Яна Гойваэрта и Стивена Левитана в их незаменимой книге Книга регулярных выражений : использование пустых групп захвата в качестве флажков для дополнительных условий.

Сначала мы ищем строчную букву, а если найдем ее, устанавливаем группу 1.

(?=(?:.*[a-z]())?)

Если есть заглавная буква, мы устанавливаем группу 2. Если нет, а группа 1 не установлена, происходит сбой. Здесь важен порядок: проверьте текущее состояние в первой альтернативе, затем сделайте обратное утверждение.

(?=.*[A-Z]()|\1)

Если есть цифра, мы устанавливаем группу 3; если нет, а группы 1 и 2 не установлены, произойдет сбой.

(?=.*[0-9]()|\1\2)

Наконец, если группы 1, 2 и 3 не установлены, мы ищем одно из специальных предложений. Сначала мы можем сделать обратные утверждения; если три условия уже выполнены, нас не волнует четвертое.

(?=\1\2\3|.*[.+*?^$\[\]()|{}/'#\\])
0 голосов
/ 28 мая 2010

Что касается шаблонов регулярных выражений для соответствия каждому критерию, вы можете захотеть сохранить каждый из них отдельным, таким образом, вы можете выполнять итерацию по строке и увеличивать значение Dim всякий раз, когда что-то соответствует одному из четырех различных шаблонов.

Для специальных символов вы можете, по крайней мере, очистить их, чтобы они были читабельными как таковые

\p{IsSpecials}

Это единственное изменение, которое я бы внес в шаблоны, и, конечно, вы можете комбинировать совпадение прописных и строчных букв с одним регулярным выражением, но это не имеет смысла, поскольку они являются различными критериями проверки.

Чтобы объединить прописные / строчные буквы, вы можете сделать это

[a-zA-Z]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...