2017-08-29 72 views
2

分隔的正则表达式的唯一的号码,我想验证一个逗号分隔的数字1-31唯一的(不重复)的列表。用逗号

  • 2,4,6,7,1是有效的输入。
  • 2,2,6-无效
  • 2是有效
  • 2,是无效
  • 1,2,3,4,15,6,7,31有效
  • 1,2, 3,4,15,6,7,32无效
  • 20,15,3

    我试图 ^((([0]?[1-9])|([1-2][0-9])|(3[01]))(?!([0]?[1-9])|([1-2][0-9])|(3[01])*,\\1(?!([0]?[1-9])|([1-2][0-9])|(3[01])),但它接受重复号码

+2

你为什么不通过分隔符分裂号码列表,然后在迭代的对象重复检查? – ctwheels

+0

你的名单有固定数量的数字,它不能超过? ,无论如何,我会建议你打破这个问题,而不是在1个正则表达式中完成:可能只有一个正则表达式来验证逗号数字格式是否正确,然后在逗号上分割并通过循环来验证数字是否是唯一的一个hashset –

+0

这感觉就像分裂成一个列表,并在那里做的行为会更好,不是一个很好的使用正则表达式 – sniperd

回答

3

对于超过1位的数字范围,只需在捕获组和反向引用的
左右添加字边界。
隔离一个完整的数字。

这尤其是一个已经麻木范围1-31

^          # BOS 
(?!          # Validate no dups 
     .* 
     (          # (1 start) 
      \b 
      (?: [1-9] | [1-2] \d | 3 [0-1])  # number range 1-31 
      \b 
    )          # (1 end) 
     .* 
     \b \1 \b 
) 
(?: [1-9] | [1-2] \d | 3 [0-1])  # Unrolled-loop, match 1 to many numb's 
(?:          # in the number range 1-31 
     , 
     (?: [1-9] | [1-2] \d | 3 [0-1]) 
)* 
$          # EOS 

var data = [ 
 
     '2,4,6,7,1', 
 
     '2,2,6', 
 
     '2,30,16,3', 
 
     '2,', 
 
     '1,2,3,2', 
 
     '1,2,2,3', 
 
     '1,2,3,4,5,6,7,8' 
 
     ]; 
 
     
 
     data.forEach(function(str) { 
 
     document.write(str + ' gives ' + /^(?!.*(\b(?:[1-9]|[1-2]\d|3[0-1])\b).*\b\1\b)(?:[1-9]|[1-2]\d|3[0-1])(?:,(?:[1-9]|[1-2]\d|3[0-1]))*$/.test(str) + '<br/>'); 
 
     });

+0

你是一个天才再次感谢。如果您有任何教程,我将不胜感激 –

2

我完全同意,有比正则表达式更好的方法来查找重复的,但如果你必须这样做,因为正则表达式,这里有一个方法(取决于您正则表达式的味道)。

查看regex101(我已多和扩展只是用于测试和可读性)。

^ 
(?!.*\b(\d+)\b.*\b\1\b) 
(0?[1-9]|[12][0-9]|3[01]) 
(,(0?\d|[12][0-9]|3[01]))* 
$ 

说明:

  • (?!.*\b(\d+)\b.*\b\1\b)是一种消极的前瞻,以确保有没有重复
  • (0?[1-9]|[12][0-9]|3[01])相匹配的第一个数字
  • (,(0?\d|[12][0-9]|3[01]))*比赛更多的

注:更新使用单词边界 - 基于答案f rom @sln

2

我已经创建了一个可以做到这一点的模式。

图案:^((?!(\d+),[^\n]*\b\2\b)([1-9]\b|[1-2]\d|3[0-1])(,(?1))?)$

demo

的简短说明。

  • ^ - 比赛开始线
  • (?!(\d+),[^\n]*\b\2\b)的 - 展望,以确保下一个号码,不重复
    • (\d+) - 抓下一个数字
    • ,[^\n]* - 一个逗号紧跟任何东西,但新行
    • \b\2\b - 下一个数字再次重复
  • ([1-9]\b|[1-2]\d|3[0-1]) - 检查下一个号码1-31之间
    • [1-9]\b - 检查单个数字。边界用于防止两位数字匹配。检查检查是否有30,31
  • (,(?1))?)如果随后在主模式逗号递归如果重复下一个数字 -
  • [1-2]\d - 检查10-29
  • 3[0-1]
  • , - 检查后跟acomma
  • (?1) - 主模式上的递归。
  • $ - 线

末更新:忘了检查1-31