[英]Regex to validate 3 repeating characters
我正在尝试验证密码,该密码不应该允许3个重复字符,无论它们在字符串中的位置如何。
例如 :
121121 - 未接受,因为1出现超过3次。
121212 - 接受,因为1和2只出现3次
我试过这个
([0-9])\1{2,}
但它的验证仅连续重复数字。
我不建议对这样的事情使用正则表达式,因为将密码收集到Map
中会更容易,其中每个字符的计数都保持不变。 然后,您可以检查是否存在任何数量超过3
字符:
password.chars()
.boxed()
.collect(Collectors.groupingBy(i -> i, Collectors.counting()))
.values()
.stream()
.anyMatch(i -> i > 3);
如果password
中出现的字符超过3
次,则返回true
否则返回false
。
使用带有反向引用的负面预测的正则表达式:
boolean ok = str.matches("((.)(?!(.*\\2){3}))+");
查看现场演示 。
在英语中,这个正则表达式说“每个角色一定不能再出现3次”。
正则表达式的解决方案是非常低效的 。 请考虑从纯粹的学术兴趣来对待这个答案。
使具有4个或更多相同char的字符串失败的模式是
^(?!.*(.).*\1.*\1.*\1).*
如果您需要精确模式,最后一个.*
可能会被更严格的模式替换。
请参阅正则表达式演示 。
这里的主要部分是(?!.*(.).*\\1.*\\1.*\\1)
负向前瞻。 它匹配任何0+字符(如果使用Pattern.DOTALL
,任何字符包括换行符),尽可能多,然后它匹配并捕获 (带(.)
)任何字符到组1,然后匹配任何0+字符跟随用同样的char 3次。 如果找到(匹配)模式,则整个字符串匹配失败。
为什么效率低下? 该模式在很大程度上依赖于回溯。 .*
所有字符抓取到字符串的末尾,然后引擎回溯,尝试为后续子模式提供一些文本。 您可能会在此处看到回溯步骤 。 越多.*
,模式消耗的资源越多。
为什么懒惰的变种不是更好? ^(?!.*?(.).*?\\1.*?\\1.*?\\1).*
看起来更快一些字符串,如果重复字符看起来接近每个字符串会更快其他和字符串的开头。 如果它们位于字符串的末尾,则效率会降低。 因此,如果前一个正则表达式在77个步骤中匹配121212
,则当前正则表达式也将采用相同数量的步骤。 但是,如果您针对1212124444
测试,您将看到懒惰变体在139步后失败 ,而贪婪变体将在58步之后失败 。 反之亦然, 4444121212
将导致懒惰的正则表达式更快失败, 14步骤与211步骤与贪婪的变体 。
在Java中,您可以使用它
s.matches("(?!.*(.).*\\1.*\\1.*\\1)")
要么
s.matches("(?!.*?(.).*?\\1.*?\\1.*?\\1)")
在生产中使用雅各布的解决方案 。
你能用地图吗?
public static void main(String[] args) {
System.out.println(validate("121121"));
System.out.println(validate("121212"));
}
static boolean validate(String s)
{
HashMap<Character, Integer> map = new HashMap<>();
for (Character c : s.toCharArray())
{
if (map.containsKey(c))
{
map.put(c, map.get(c) + 1 );
}
else
{
map.put(c , 1);
}
}
for (Integer count : map.values())
{
if (count > 3)
return false;
}
return true;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.