【问题标题】:regex to find numbers with unique digits正则表达式查找具有唯一数字的数字
【发布时间】:2013-11-25 23:30:12
【问题描述】:

我想查找没有重复数字的10位数字,例如:

1123456789 //fail, there are two 1's
6758951230 //fail, there are two 5's
6789012345 //pass, each digit occurs once only. 

目前我正在使用正则表达式,但只能匹配 10 位数字(它不检查重复项。我正在使用这个正则表达式:

[0-9]{10}

这可以用正则表达式完成还是有更好的方法来实现这一点?

【问题讨论】:

  • 你必须使用反向引用来检查一个数字是否还没有被捕获。
  • 这不是一个适合正则表达式的问题。只需编写一个简单的循环,并使用一个 boolean[10] 数组来记录每个数字的出现情况。
  • @JimGarrison 这绝对正则表达式的工作:请参阅my answer 了解如何做到这一点。永远不要说永远:)
  • 对于 > 10 位字符串中的唯一 10 位数字,我看不到使用正则表达式的解决方案,除非它是布尔类型断言(就像我发布的那样)。也许它可能,但可能不使用* 量词。

标签: java regex


【解决方案1】:

这个正则表达式有效:

^(?!.*(.).*\1)\d{10}$

这使用带有反向引用的锚定否定前瞻来断言没有重复的字符。

查看live demo 处理您的示例。

在java中:

if (str.matches("^(?!.*(.).*\\1)\\d{10}"))
    // number passes

【讨论】:

  • 你可以让它为一个浮动(子字符串)10位数字工作吗?没有锚可以工作吗?
  • @sin 当然,但你能举例说明你的意思吗?例如12345.067891234.0123456789 或其他?
  • 112346578910100010 只是一个简单的例子。因为您的正则表达式使用了许多量词,所以如果没有锚,它总是会超过 10 位数的边界。除非你能想到另一种方法,但我认为像我发布的布尔类型的正则表达式是唯一的方法。
  • @sln 我的回答正确:它与1111234567890000 不匹配。仔细阅读我的答案:String.matches() 必须匹配 .*whole* 字符串才能返回 true,因此 ^ 和 $ 是隐含的(自动添加到正则表达式的前后)。即str.matches("foo")String.matches("^foo$") 相同,因此不需要锚。
  • @Huei 见this page的“解释”部分
【解决方案2】:

试试这个(?:([0-9])(?!.*\1)){10},如果您一次验证一个数字,这将起作用。

这应该可以(?:([0-9])(?!\d*\1)){10} 搜索唯一的 10 位序列的每个出现,但它会因12345678901234567890 而失败,将找到最后一个有效部分 1234567890 而不是忽略它。

来源及说明:https://stackoverflow.com/a/12870549/1366360

【讨论】:

  • @OGHaza 请给我你测试过的号码
  • regexplanet.com/advanced/java/index.html 进行了测试,适用于 OP 提出的两种情况
  • 例如1111111111,但仔细观察,这可能几乎可以工作(它会查找不重复的 10 位数字集,即接下来的 10 位数字不能与前 10 个)。
  • 那是因为它们必须以 10 个为一组。9 位将始终失败,11 位将始终失败。
  • @OGHaza 好的,原因是我添加了这个{10},结果我允许每个字符连续重复最多10次。试试^(?:([0-9])(?!.*\1))*$ 但是我们还是需要设置10个字符的长度,给我一点时间。
【解决方案3】:

由于? 的存在,这是具有较少回溯 的最短且高效的正则表达式。

适用于任何长度的输入:

!/(.).*?\1/.test(number)

例子:

!/(.).*?\1/.test(1234567890) // true
!/(.).*?\1/.test(1234567490) // false - note that it also works for repeated chars which are not adjacent.

Demo
- 检查重复数字
- 与您想要的相反,因为rubular 不允许!

【讨论】:

    【解决方案4】:

    lancemanfv 正则表达式参考 https://stackoverflow.com/a/12870549/1366360 是一个很好的参考,但建议的正则表达式略有偏差。

    不如试试

    ^(?:([0-9])(?!.*\1)){10}$ 
    

    这将匹配任何以 10 个不同数字开头和结尾的字符串。

    如果您想检查(并提取)较长的字符串是否包含 10 位数字,每个数字不同,请使用此

    ((?:([0-9])(?!.*\2)){10})*
    

    然后您可以使用编号引用来提取匹配的编号

    【讨论】:

    • 锚定的正则表达式仅适用于 10 位字符串,但第二个正则表达式可能永远不会起作用,因为它使用了许多量词 .*,它总是会超过 10 位的边界。
    【解决方案5】:

    每次都有效(我看到了这个问题) -

    修订以在 (?! \10 ) 断言之前定义 Grp 10。 \1-\9 始终被视为反向引用(> \10,括号必须在引用之前)。
    所以也让它们都一样。

    注意 - 这可用于查找浮动(子字符串)10 uinque 数字。不需要锚。
    仅供参考 - 对于 Perl,\g{#}(或 \k'name')语法可以在定义组之前使用,无论组号是多少。

     #  "(?:((?!\\1)1)|((?!\\2)2)|((?!\\3)3)|((?!\\4)4)|((?!\\5)5)|((?!\\6)6)|((?!\\7)7)|((?!\\8)8)|((?!\\9)9)|((?!\\10)0)){10}"
    
    
     (?:
          (                      # (1)
               (?! \1 )
               1
          )
       |  (                      # (2)
               (?! \2 )
               2
          )
       |  (                      # (3)
               (?! \3 )
               3
          )
       |  (                      # (4)
               (?! \4 )
               4
          )
       |  (                      # (5)
               (?! \5 )
               5
          )
       |  (                      # (6)
               (?! \6 )
               6
          )
       |  (                      # (7)
               (?! \7 )
               7
          )
       |  (                      # (8)
               (?! \8 )
               8
          )
       |  (                      # (9)
               (?! \9 )
               9
          )
       |  (                      # (10)
               (?! \10 )
               0
          )
     ){10}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-21
      • 1970-01-01
      • 2010-09-26
      • 1970-01-01
      相关资源
      最近更新 更多