Существует ли более краткое регулярное выражение для выполнения этой задачи?

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

Пароли должны содержать по крайней мере 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 regexes в один? Но я предполагаю выполнение, которое не позволило бы мне проверять, соответствуют ли по крайней мере 3 из критериев.

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

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

5
задан Matt M 28 May 2010 в 13:20
поделиться

6 ответов

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

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

6
ответ дан 13 December 2019 в 05:31
поделиться

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

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,}»
2
ответ дан 13 December 2019 в 05:31
поделиться

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

Это и есть самая сложная часть: "3 из 4", это трудно перевести в (один) регекс. То, как вы решаете эту проблему сейчас, вполне подходит, IMO.

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

Специальные символы 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

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

^    // 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 ')'
1
ответ дан 13 December 2019 в 05:31
поделиться

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

"^(?=(?:.*[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
ответ дан 13 December 2019 в 05:31
поделиться

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

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

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

3
ответ дан 13 December 2019 в 05:31
поделиться

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

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

\p{IsSpecials}

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

Для объединения наборов верхнего и нижнего регистра можно сделать следующее

[a-zA-Z]
0
ответ дан 13 December 2019 в 05:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: