Как проверить, содержит ли строка строчную букву, заглавную букву, специальный символ и цифру? - PullRequest
22 голосов
/ 10 января 2012

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

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

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

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

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

Ответы [ 6 ]

38 голосов
/ 10 января 2012

Регулярные выражения не очень хороши для тестов, где требуется все из нескольких условий.

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

Ваш код может быть дробно медленнее, но его будет легче читать и поддерживать, например,

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;
}

РЕДАКТИРОВАТЬ фиксированные кавычки - слишком много занимался программированием на JS ...

14 голосов
/ 10 января 2012

Я согласен, что ответ @ 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 символов приведенный выше код был в два раза быстрее.Хотя, думаю, теперь можно сказать, что этот код труднее читать!Не бери в голову!

13 голосов
/ 10 января 2012

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

String regex = "^(?=.*?\\p{Lu})(?=.*?[\\p{L}&&[^\\p{Lu}]])(?=.*?\\d)" + 
               "(?=.*?[`~!@#$%^&*()\\-_=+\\\\\\|\\[{\\]};:'\",<.>/?]).*$"
  1. ^ Это соответствует началу строки.Это не обязательно необходимо для работы, но я считаю, что это помогает удобочитаемости и понимания.Кроме того, использование его в тех случаях, когда это возможно, часто приводит к значительному улучшению производительности и почти никогда не является штрафом.

  2. (? = X ) Это называется положительным прогнозом.По сути, мы говорим: «За началом строки (^) должна следовать эта вещь X , чтобы найти совпадение, но НЕ перемещайте курсор до концаиз X , оставайтесь в начале строки. (это часть "просмотра вперед".)

  3. . *? \ p {Lu} есть символы посленачало строки, пока вы не найдете заглавную букву. Она не будет соответствовать, если заглавная буква не найдена. Мы используем \ p {Lu} вместо AZ, потому что мы не хотим, чтобы люди из других частей мира подбрасывалиих руки и жалуются на то, как наше программное обеспечение было написано невежественным американцем.

  4. Теперь мы возвращаемся к началу строки (мы возвращаемся, потому что мы использовали lookahead) и начинаем поискfor. *? [\ p {L} && [^ \ p {Lu}]] сокращение от «все буквы минус столицы» (следовательно, соответствует нижнему регистру).

  5. .*? \ d +. *? [`~! @ # $% ^ & * () \ -_ = + \\\ | \ [{\]};: '\", <.> /?] повторить дляцифры и список специальных символов.

  6. . * $ Сопоставьте все остальное до конца строки.Мы делаем это только из-за семантики методов match в java, которые проверяют, соответствует ли строка whole регулярному выражению.Вы можете оставить эту часть и использовать метод Matcher # find () и получить тот же результат.

  7. «Сова» - одна из лучших книг, когда-либо написанных на любую техническую тему.. И это быстро и быстро читать.Я не могу рекомендовать это достаточно.

7 голосов
/ 10 января 2012

Поскольку они не будут отображаться в каком-либо определенном порядке, вам потребуются предварительные утверждения для каждого требуемого класса символов:

(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~!@#$%\^&*()\-_=+\|\[{\]};:'",<.>/?])

(ПРИМЕЧАНИЕ: обратная косая черта, каретка, дефис и квадратные скобки могут быть специальными внутридиапазона, они должны быть экранированы от обратной косой черты, если они появляются в диапазоне, как показано в четвертом утверждении.)

Эту конструкцию можно сделать значительно более читабельной, используя пробел и комментарии, если ваш вариант регулярного выражения поддерживает *Модификатор 1006 *.В 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
(?=.*[~!@#$%\^&*()\-_=+\|\[{\]};:'",<.>/?])
             # look ahead for at least one of the listed symbols
0 голосов
/ 10 января 2012

\w: используется для сопоставления буквенно-цифровых символов (буквы могут быть большими или маленькими)\W: используется для сопоставления специальных символов

Я думаю, этот RegEx будет вам полезен:

[\w|\W]+

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

0 голосов
/ 10 января 2012

Вы ищете классы символов .

  • Большая буква: [AZ]
  • Маленькая буква: [az]
  • Цифра: [0-9] или \ d
  • Специальный символ: [^ A-Za-z0-9] (т. Е. Ни один из остальных, где ^ отрицает класс)

Если вы хотите проверить «то» или «то», вы можете объединить эти диапазоны.Например, большие или маленькие буквы будут [A-Za-z].

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