Подтвердить что ты не робот

Как проверить, содержит ли строка строчную букву, прописную букву, специальный символ и цифру?

Я много гуглился, и я не нашел ответа на свой вопрос:

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

  • Верхняя буква
  • Строчная буква
  • Digit
  • Специальный символ: ~`[email protected]#$%^&*()-_=+\|[{]};:'",<.>/?

Итак, мне нужна хотя бы прописная буква и хотя бы маленькая буква и, по крайней мере, цифра и, по крайней мере, специальный символ.

Я уверен, что ответ очень прост, но я не могу его найти. Любая помощь приветствуется.

4b9b3361

Ответ 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.