我提出以下正则表达式:
(?<number>[1-9]|[12]\d|3[01]){0}(?<thing>\g<number>-\g<number>|\g<number>){0}^(\g<thing>,)*\g<thing>$
看起来很糟糕,但实际上并不是 :) 实际上,构造 (?<name>...){0}
允许我们定义一个命名的正则表达式,并说它不匹配其定义的位置。因此,我定义了一个数字模式称为 number
和一个我称之为事物的模式,即范围或数字,称为 thing
。接下来,我知道您的表达式是这些事物的序列,因此我使用命名的正则表达式 thing
用构造 \g<thing>
来构建它。它给出了 (\g<thing>,)*\g<thing>
。这很容易阅读和理解。如果您允许在正则表达式中将空格视为不重要,则甚至可以像这样缩进:
(?<number>[1-9]|[12]\d|3[01]){0}
(?<thing>\g<number>-\g<number>|\g<number>){0}
^(\g<thing>,)*\g<thing>$/
我已经使用Ruby 1.9.2进行了测试。你的正则表达式引擎应该支持命名组,以允许这种清晰度。
irb(main):001:0> s1 = '1-5,5,15-29'
=> "1-5,5,15-29"
irb(main):002:0> s2 = '1,28,1-31,15'
=> "1,28,1-31,15"
irb(main):003:0> s3 = '15,25,3'
=> "15,25,3"
irb(main):004:0> s4 = '1-24,5-6,2-9'
=> "1-24,5-6,2-9"
irb(main):005:0> r = /(?<number>[1-9]|[12]\d|3[01]){0}(?<thing>\g<number>-\g<number>|\g<number>){0}^(\g<thing>,)*\g<thing>$/
=> /(?<number>[1-9]|[12]\d|3[01]){0}(?<thing>\g<number>-\g<number>|\g<number>){0}^(\g<thing>,)*\g<thing>$/
irb(main):006:0> s1.match(r)
=>
irb(main):007:0> s2.match(r)
=>
irb(main):008:0> s3.match(r)
=>
irb(main):009:0> s4.match(r)
=>
irb(main):010:0> '1-1-1-1'.match(r)
=> nil