【问题标题】:Password validation by regex通过正则表达式验证密码
【发布时间】:2015-04-20 18:47:41
【问题描述】:
System.out.println(Pattern.matches("[A-Z]{1,}[a-z]{1,}[0-9]{2,}[@#$%]+[ ]*", "DEFabc45$  "));

但是当我传递passW@ord45 之类的字符串时它不起作用。意思是我不应该遵循这里写的正则表达式顺序模式。

以下是下面给出的条件:

写一个函数boolean isValidPassword (String password)一个密码如果满足以下条件是有效的:

  1. 密码长度必须大于10(不计 空格)。
  2. 密码必须至少包含一个大写字母和一个小写字母
  3. 密码必须至少包含 2 位数字,如果没有 2 位数字,请查看下一个条件。
  4. 密码必须至少包含给定集合中的一个特殊字符 - {$, @, _, -, ., /}

【问题讨论】:

  • Regex 在这里是错误的工具 - 虽然您可能能够对给定的要求进行编码,但它会导致非常复杂的表达式。几乎可以肯定的是,当您稍后再回来时,它几乎无法理解并因此无法维护。使用 Java 中的一些简单的代码语句会更好地解决这个问题,而且可读性要好得多。
  • 通常我都是正则表达式,但一旦你进入“如果不是这样,那么”的逻辑,正则表达式可能不是方式。
  • @Srb1313711:不要假设,学习,测试自己,分析情况是不重复“主流断言”的唯一方法。
  • @CasimiretHippolyte 我没有假设任何事情我什至没有说这是不可能的,我只是说可能有更好的方法来解决这个问题

标签: java regex


【解决方案1】:

你可以使用@davide评论中链接的方法,所以基本上:

(?=(?: *\\S){10})(?=.*[a-z])(?=.*[A-Z])(?=.*[$@_./-]|.*[0-9].*[0-9])

但是,在任何地方使用.* 会产生很多回溯(尤其是.*[0-9].*[0-9]),因此防止这种情况的方法更加明确:

(?=(?: *\\S){10,})(?=[^a-z]*[a-z])(?=[^A-Z]*[A-Z])[^$@_./0-9-]*+(?:[$@_./-]|[0-9][^0-9]*[0-9])

关于这两种模式中使用的特征:

\\S 是一个速记字符类:所有非空白字符

(?=...) 是一个零宽度断言(一种测试),称为前瞻,表示后跟。因此,您可以使用它从同一位置测试多个断言,如下所示:(?=..)(?=..)(?=..)...,因为不消耗字符。

*请注意,在第二种模式中,我选择不使用前瞻,因为没有更多规则,是否使用字符并不重要。

所以每个前瞻都包含一个规则:

规则 1:至少 10 个非空格字符

(?=
    (?: *\\S){10}  # a group with optional spaces and one non space character
                   # the group is repeated 10 times, so there are at least
                   # 10 characters that are not a space
)

规则 2a:小写字母

(?=
    [^a-z]*    # zero or more characters that are not a lowercase letter
    [a-z]      # until a lowercase letter
)

规则 2B:大写字母,(与 2a 相同,但带有 A-Z

规则 3 和 4 组合在一个子模式中,如前所述:

[^$@_./0-9-]*+          # all that is not a digit or a special character
                        # Note: I have added a possessive quantifier make the whole
                        # pattern to fail faster if the next group fails 
(?: # two possibilities:
    [$@_./-]            # a special character
  |                  # OR
    [0-9][^0-9]*[0-9]   # two digits: a digit, other characters, an other digit 
) 

您可以将这些模式与lookingAt 一起使用,因为不需要在末尾锚定它们(根据您的要求)或使用matches,但您需要在末尾添加.* 以达到字符串的结尾。

【讨论】:

  • “当你稍后再看它时,几乎肯定无法理解并因此维护它”我认为你很好地说明了我的观点:D
  • @Paolo:我们可以和学习阅读做一个类比:当你认出单词和习语、构式时,你可以立即理解句子的意思。无法理解一种模式(在这里如此基本且众所周知)是由于缺乏技能。但是如果获得了这项技能,重写或修改这种模式需要 5 分钟的淋浴时间,就像其他任何事情一样。
  • 我认为这个解决方案是无效的。条件为:“不计算空格”。而不是:“可能不包含空格”。我认为最好将正则表达式与“正常”检查和方法调用(如.replace(" ","").length() > 10 等)混合使用。
  • @UniversE: 不,这里考虑了空格:(?: *\\S){10},量词 * 使空格成为可选的,所以 {10} 将重复非空格字符 10次。请注意,为了更严格,您可以写(?:\\s*\\S){10}(但通常很难在密码字段中放置制表符或换行符,但谁知道呢?)。看这里:regex101.com/r/yX1hP2/1
  • @CasimiretHippolyte 哦,好吧-现在我明白了……您捕获一个字符和任何前面的空格并将其计为一个。所以____1|__2|___3|__________4|等等..(这里_是一个空格)
猜你喜欢
  • 2011-05-06
  • 2016-10-19
  • 2011-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多