2017-08-29 63 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