如何用正则表达式验证字符串中所有数字互不重复?
三位数字互不重复的正则验证问题排查与解决
需要验证字符串为三位互不重复的数字,例如"123"符合要求,"112""131"不符合。但现有Java代码会误判部分不符合条件的字符串(如"121"被判定为true),以下是问题分析和修正方案。
现有代码的问题分析
你写的正则"([0-9])(?!\\1)[0-9](?!\\1)[0-9]"存在两个核心问题:
- 负向前瞻逻辑错误:
(?!\\1)是断言「当前位置之后没有匹配组1的内容」,而非「当前字符不等于组1」。对于第三位数字,由于它是字符串最后一位,后面没有内容,(?!\\1)永远为真,导致第三位可以和第一位重复(比如"121"的第三位1会被允许)。 - 未检查后两位重复:正则仅约束第二位、第三位不等于第一位,但没检查第二位和第三位是否重复(比如"122"会被错误判定为true)。
正确的正则写法
针对三位互不重复数字的需求,有两种可靠的正则方案:
方案一:全局重复检测(通用型,可扩展到任意长度数字)
^(?![0-9]*([0-9])[0-9]*\\1)[0-9]{3}$
逻辑:通过负向前瞻断言整个字符串中不存在重复出现的数字,再匹配三位数字。
方案二:逐位约束(针对三位数字的精确写法)
^([0-9])(?!\\1)([0-9])(?!\\1|\\2)[0-9]$
逻辑:
- 捕获第一位数字为组1;
- 第二位数字必须不等于组1,捕获为组2;
- 第三位数字必须不等于组1和组2。
修正后的Java代码
public class MyClass { public static void main(String args[]) { String[] value = {"123","951","121","355","110"}; for (String s : value){ System.out.println("\"" + s + "\"" + " -> " + validate(s)); } } public static boolean validate(String s){ // 使用方案一的正则 return s.matches("^(?![0-9]*([0-9])[0-9]*\\1)[0-9]{3}$"); // 或者使用方案二: // return s.matches("^([0-9])(?!\\1)([0-9])(?!\\1|\\2)[0-9]$"); } }
测试结果
运行修正后的代码,输出如下:
"123" -> true "951" -> true "121" -> false "355" -> false "110" -> false
内容的提问来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

