如何检查字符串是否包含小写字母,大写字母,特殊字符和数字?

Laj*_*pad 21 java regex

我一直在谷歌搜索,我没有找到我的问题的答案:

如何检查正则表达式字符串是否包含以下每个中的至少一个:

  • 大写字母
  • 小写字母
  • 数字
  • 特殊字符: ~`!@#$%^&*()-_=+\|[{]};:'",<.>/?

所以,我至少需要一个大写字母至少一个小写字母至少一个数字至少一个特殊字符.

我确定答案很简单,但我找不到.任何帮助是极大的赞赏.

Aln*_*tak 38

对于需要满足所有条件的测试,正则表达式不是很好.

因此,最简单的答案是不要试图同时测试它们,而只是依次尝试四个类中的每一个.

您的代码可能是分数慢,但它会更容易阅读和维护,如

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;
}
Run Code Online (Sandbox Code Playgroud)

编辑固定引号 - 一直在做太多该死的JS编程......

  • @fge:不幸的是,String没有`find()`方法,我没有看到告诉人们使用`Pattern.compile("[AZ]")的任何意义.matcher(pass).find( ))```pass.matches(".*[AZ].*")`完成工作.唯一需要注意的是字符串中是否有行分隔符(`\n`,`\ r``等),我不认为这是一个问题. (6认同)
  • 如果您选择的话,这还允许您向用户返回特定于条件的错误消息。 (2认同)

Mar*_*des 14

我同意@ 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;
    }
Run Code Online (Sandbox Code Playgroud)

当使用10个字符的密码运行100,000次时,上述代码的速度是原来的两倍.虽然,我想现在你可以说这段代码更难读!没关系!


Aff*_*ffe 14

这可以在java中作为单个正则表达式执行,但我个人会使用类似Mark Rhodes提供的解决方案.随着规则变得更加复杂,这将变得荒谬快速(如果它还没有......).

String regex = "^(?=.*?\\p{Lu})(?=.*?[\\p{L}&&[^\\p{Lu}]])(?=.*?\\d)" + 
               "(?=.*?[`~!@#$%^&*()\\-_=+\\\\\\|\\[{\\]};:'\",<.>/?]).*$"
Run Code Online (Sandbox Code Playgroud)
  1. ^这匹配字符串的开头.这不是必须的,但我发现它有助于提高可读性和理解力.此外,使用它时,您通常可以大幅提升性能,几乎不会受到惩罚.

  2. (?= X)这称为正向前瞻.基本上我们所说的是"字符串的开头(^)必须跟着这个东西X才能匹配,但是不要将光标前进到X的末尾,保持在行的开头.(那就是"向前看"部分.)

  3. .*?\ p {Lu}在行开头后吃字符,直到找到大写字母.如果没有找到大写字母,则无法匹配.我们使用\ p {Lu}代替AZ,因为我们不希望来自世界其他地方的人举手投诉我们的软件是如何由一个无知的美国人写的.

  4. 现在我们回到行的开头(我们回去因为我们使用了前瞻)并开始搜索.*?[\ p {L} && [^\p {Lu}]]简写为"所有字母,减去首都"(因此匹配小写).

  5. .*?\ d +.*?[`〜!@#$%^&*()\ -_ = + \\\ |\[{\]};:'\",<.> /?]重复用于数字和特殊字符列表.

  6. .*$匹配其他所有内容,直到行尾.我们这样做只是因为java中'matches'方法的语义,看看整个字符串是否与正则表达式匹配.您可以离开这部分并使用Matcher#find()方法并获得相同的结果.

  7. 猫头鹰是有史以来最好的书籍之一. 而且阅读时间短而快.我不能推荐它.

  • 当然,为什么不呢?! (3认同)

Met*_*aEd 7

因为这些不会以任何特定顺序出现,所以每个必需的字符类都需要前瞻断言:

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

(注意:因为反斜杠,插入符号,连字符和方括号在一个范围内可能是特殊的,如果它们出现在范围内,它们应该反斜杠转义,如第四个先行断言所示.)

如果您的正则表达式变体支持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
(?=.*[~!@#$%\^&*()\-_=+\|\[{\]};:'",<.>/?])
             # look ahead for at least one of the listed symbols
Run Code Online (Sandbox Code Playgroud)

  • 这证明了我的观点 - 我一直在使用regexps,因为上帝知道多少年了,并且从未使用过前瞻性断言,并且很难读懂这一点.任何人都可以阅读带有四个简单正则表达式的版本. (3认同)