Прежде всего, жаль о хромом заголовке, но я не мог думать о лучшем. Я должен протестировать пароль для обеспечения следующего:
Пароли должны содержать по крайней мере 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. Я не могу выразить достаточно, как потрясающий я думаю, что этот сайт.
То, как это сделано у вас, примерно настолько хорошо, насколько это возможно. Вы могли бы сделать все это в одной строке, но это было бы ужасно запутанно и ничем не помогло бы.
Подумайте о том, что вы пытаетесь сделать; вы хотите проверить четыре различных критерия. Поскольку каждый критерий - это, по сути, одно сравнение, вы захотите проверить каждый из них по отдельности, что вы и делаете.
Я считаю, что это работает, но это просто показывает, насколько уродливым это могло бы стать. Вы не получите ни скорости, ни удобочитаемости.
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,}»
Есть ли способ объединить все 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 ')'
Просто для удовольствия, вот изящный способ выполнить работу в одном регулярном выражении:
"^(?=(?:.*[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|.*[.+*?^$\[\]()|{}/'#\\])
Я думаю, что ваш подход здесь разумный. Понятно, что именно вы пытаетесь достичь (в том смысле, что правильное регулярное выражение не было бы), и это работает!
Большинство языков имеют очень хорошую документацию по обработке регулярных выражений, поэтому я предлагаю сначала поискать ее. В противном случае я считаю, что документация JavaScript MDC regex очень хороша для подмножества регулярных выражений, поддерживаемых этим языком (что охватывает наиболее реалистичное использование).
Еще один совет - вам не нужно экранировать все эти специальные символы, когда вы находитесь внутри набора символов (квадратные скобки). "[{} [.? * ^ $ |]" совершенно верно. (Вам, очевидно, нужно избежать) и ваши разделители (").
Что касается шаблонов regex для соответствия каждому критерию, вы можете захотеть сохранить каждый из них отдельно, таким образом вы сможете итерационно просматривать строку и увеличивать счетчик Dim каждый раз, когда что-то соответствует одному из четырех различных шаблонов.
Для специальных символов вы можете, по крайней мере, очистить их, чтобы они были читаемы как таковые
\p{IsSpecials}
Это единственное изменение, которое я бы внес в шаблоны, и, конечно, вы можете объединить соответствие верхнего и нижнего регистра в один регекс, но это не будет иметь смысла, поскольку это разные критерии проверки.
Для объединения наборов верхнего и нижнего регистра можно сделать следующее
[a-zA-Z]