java - 正则表达式验证字符串中是否有 4 个不同的字符

标签 java regex

我想强制一个字符串中包含 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).)).*

Demo on regex101

使用String.matches():

input.matches("(.)(?>.*?((?!\\1).))(?>.*?((?!\\1|\\2).))(?>.*?((?!\\1|\\2|\\3).)).*")

(?>pattern) 构造可防止在退出内部模式后回溯到组中。这用于将捕获组“锁定”到每个不同字符的第一次出现,因为即使您稍后在字符串中选择不同的字符,结果也是相同的。

此正则表达式的行为与普通程序相同,它从左到右循环,根据一组不同的字符检查当前字符,如果当前字符不在集合中,则将其添加到集合中。

由于这个原因,惰性量词 .*? 变得很重要,因为它搜索迄今为止尚未出现的最接近的字符。

关于java - 正则表达式验证字符串中是否有 4 个不同的字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30280135/

相关文章:

Java 开源工作流引擎

java - 如何用Java读取和写入ppm

java - maven 插件之间的区别 ( assembly-plugins , jar-plugins , shaded-plugins )

java - 使用套件时的 JUnit 4 @BeforeClass 和 @AfterClass

python - 查找字符串之间的重复模式

regex - 是否使用 GNU sed 在正则表达式中转义 ( and )

regex - IIS7 URL 重写 - 如何用正则表达式中的连字符替换所有下划线?

javascript - 获取具有特定子字符串的类名的正则表达式

java - 二维数组出现问题,无法卡住一个对象并将该对象复制到右侧 90 像素

.NET 正则表达式分割多个单词或短语