Как проверить, содержит ли строка строчную букву, прописную букву, специальный символ и цифру?
Я много гуглился, и я не нашел ответа на свой вопрос:
Как я могу проверить с регулярным выражением, содержит ли строка хотя бы одно из следующих значений:
- Верхняя буква
- Строчная буква
- Digit
- Специальный символ:
~`[email protected]#$%^&*()-_=+\|[{]};:'",<.>/?
Итак, мне нужна хотя бы прописная буква и хотя бы маленькая буква и, по крайней мере, цифра и, по крайней мере, специальный символ.
Я уверен, что ответ очень прост, но я не могу его найти. Любая помощь приветствуется.
Ответы
Ответ 1
Это делает то, что вы хотите в java как одно регулярное выражение, хотя я лично использовал бы что-то вроде решения, предоставленного Марком Роудсом. Это будет смешно быстро (если оно еще не...) по мере усложнения правил.
String regex = "^(?=.*?\\p{Lu})(?=.*?[\\p{L}&&[^\\p{Lu}]])(?=.*?\\d)" +
"(?=.*?[`[email protected]#$%^&*()\\-_=+\\\\\\|\\[{\\]};:'\",<.>/?]).*$"
-
^ Это соответствует началу строки. Для этого не нужно строго работать, но я считаю, что это помогает читать и понимать. Кроме того, используя его, когда вы часто можете добиться большого улучшения производительности и почти никогда не накладываете штраф.
-
(? = X) Это называется положительным взглядом. В основном то, что мы говорим, это "начало строки (^) должно сопровождаться этой вещью X для соответствия, но DO NOT продвигать курсор до конца X, оставаться на начало строки (это часть" смотреть вперед".)
-
. *?\p {Lu} есть символы после начала строки, пока не найдете заглавную букву. Это не будет соответствовать, если не будет найдена заглавная буква. Мы используем \p {Lu} вместо A-Z, потому что мы не хотим, чтобы люди из других частей света поднимали руки и жаловались на то, как наше программное обеспечение было написано невежественным американцем.
-
Теперь мы возвращаемся к началу строки (мы возвращаемся назад, потому что мы использовали lookahead) и начинаем поиск. *? [\ p {L} && [^\p {Lu} ]] сокращение для "всех букв, минус капиталов" (следовательно, соответствует нижнему регистру).
-
. *?\d+. *? [`~! @# $% ^ & *()\-_ = + \\\ |\[{\]};: '\", <. > /?] повторите для цифр и для списка специальных символов.
-
. * $Сопоставьте все остальное до конца строки. Мы делаем это только из-за семантики методов "совпадений" в java, которые видят, что вся строка соответствует регулярному выражению. Вы можете оставить эту часть и использовать метод Matcher # find() и получить тот же результат.
-
Сова - одна из лучших книг, когда-либо написанных на любом техническом предмете. И коротко и быстро читать. Я не могу рекомендовать его достаточно.
Ответ 2
Регулярные выражения не очень хороши для тестов, где вам нужно выполнить все несколько условий.
Самый простой ответ заключается не в том, чтобы попытаться проверить их все одновременно, а просто попробовать каждый из четырех классов по очереди.
Ваш код может быть менее медленным, но его будет легче читать и поддерживать, например.
public boolean isLegalPassword(String pass) {
if (!pass.matches(".*[A-Z].*")) return false;
if (!pass.matches(".*[a-z].*")) return false;
if (!pass.matches(".*\\d.*")) return false;
if (!pass.matches(".*[~!.......].*")) return false;
return true;
}
EDIT фиксированные метки кавычек - делали слишком много проклятого программирования JS...
Ответ 3
Я согласен с тем, что ответ @Alnitak проще всего читать, однако он страдает тем, что он должен оценивать регулярные выражения каждый раз, когда он запускается. Поскольку регулярные выражения фиксированы, имеет смысл их компилировать, а затем сравнивать с ними.
например Что-то вроде:
private static final Pattern [] passwordRegexes = new Pattern[4];
{
passwordRegexes[0] = Pattern.compile(".*[A-Z].*");
passwordRegexes[1] = Pattern.compile(".*[a-z].*");
passwordRegexes[2] = Pattern.compile(".*\\d.*");
passwordRegexes[3] = Pattern.compile(".*[~!].*");
}
public boolean isLegalPassword(String pass) {
for(int i = 0; i < passwordRegexes.length; i++){
if(!passwordRegexes[i].matcher(pass).matches())
return false;
}
return true;
}
При запуске 100 000 раз на 10-символьном пароле вышеуказанный код был в два раза быстрее. Хотя, я думаю, теперь вы можете сказать, что этот код сложнее читать! Ничего!
Ответ 4
Поскольку они не будут отображаться в каком-либо конкретном порядке, вам понадобятся утверждения lookahead для каждого требуемого класса символов:
(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[[email protected]#$%\^&*()\-_=+\|\[{\]};:'",<.>/?])
(ПРИМЕЧАНИЕ: поскольку обратная косая черта, каретка, дефис и квадратные скобки могут быть специальными внутри диапазона, они должны иметь обратную косую черту, если они появятся в диапазоне, как показано в четвертом утверждении.)
Эта конструкция может быть сделана значительно более читаемой, используя пробелы и комментарии, если ваш вариант регулярного выражения поддерживает модификатор x
. В java.util.regex
вы можете:
(?x) # extended syntax
(?=.*[A-Z]) # look ahead for at least one upper case
(?=.*[a-z]) # look ahead for at least one lower case
(?=.*[0-9]) # look ahead for at least one numeral
(?=.*[[email protected]#$%\^&*()\-_=+\|\[{\]};:'",<.>/?])
# look ahead for at least one of the listed symbols
Ответ 5
Вы ищете классы символов.
- Большая буква: [A-Z]
- Маленькая буква: [a-z]
- Цифры: [0-9] или \d
- Специальный символ: [^ A-Za-z0-9] (То есть, не любой из других, где
^
отрицает класс)
Если вы хотите протестировать 'this' или 'this', вы можете объединить эти диапазоны. Например, большие или малые буквы будут [A-Za-z]
.
Ответ 6
\w
: используется для сопоставления буквенно-цифровых (алфавиты могут быть большими или малыми)
\w
: используется для сопоставления специальных символов
Я думаю, что этот RegEx будет вам полезен:
[\w|\W]+
Здесь хороший RegEx Simulator, вы можете использовать его для создания собственного RegEx.