我想强制一个字符串中包含 4 个不同的字符。
有效示例:
"1q2w3e4r5t"
"abcd"
无效示例:
"good"
"1ab1"
关于模式的想法?
最佳答案
您应该考虑使用非正则表达式解决方案。我写这个答案只是为了展示这个问题的更简单的正则表达式解决方案。
初始解决方案
这是一个更简单的正则表达式解决方案,它断言字符串中至少有 4 个不同的字符:
(.).*?((?!\1).).*?((?!\1|\2).).*?((?!\1|\2|\3).).*
Demo on regex101 (PCRE 和 Java 对于此正则表达式具有相同的行为)
.*?((?!\1).)
, .*?((?!\1|\2).)
, ... 搜索对于下一个之前没有出现过的字符,这是通过检查该字符与之前捕获组中捕获的字符是否相同来实现的。
从逻辑上讲,量词的惰性/贪婪在这里并不重要。惰性量词 .*?
用于使搜索从最近的、以前没有出现过的字符开始,而不是从最远的字符开始。它应该会稍微提高匹配情况下的性能,因为回溯次数较少。
与String.matches()
一起使用,断言整个字符串与正则表达式匹配:
input.matches("(.).*?((?!\\1).).*?((?!\\1|\\2).).*?((?!\\1|\\2|\\3).).*")
改进的解决方案
如果您担心性能:
(.)(?>.*?((?!\1).))(?>.*?((?!\1|\2).))(?>.*?((?!\1|\2|\3).)).*
使用String.matches()
:
input.matches("(.)(?>.*?((?!\\1).))(?>.*?((?!\\1|\\2).))(?>.*?((?!\\1|\\2|\\3).)).*")
(?>pattern)
构造可防止在退出内部模式后回溯到组中。这用于将捕获组“锁定”到每个不同字符的第一次出现,因为即使您稍后在字符串中选择不同的字符,结果也是相同的。
此正则表达式的行为与普通程序相同,它从左到右循环,根据一组不同的字符检查当前字符,如果当前字符不在集合中,则将其添加到集合中。
由于这个原因,惰性量词 .*?
变得很重要,因为它搜索迄今为止尚未出现的最接近的字符。
关于java - 正则表达式验证字符串中是否有 4 个不同的字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30280135/