2014-09-12 44 views
2

比方说,我想验证一个字符串,以确保它是一个无限长的单个十进制数字整数列表,每个整数都用逗号分隔,并允许零个或多个空格。在正则表达式中,处理分隔列表中的fencepost问题的优雅方式是什么?

我想使用正则表达式来确保它是有效的。我会用这样的:

^\d(?:\s*,\s*\d)*$ 

字符串值,将匹配:

"4,0 , 9 ,3, 6" 

该字符串值不匹配:

"4,0 , 9 ,3, 6," 

事实上,这是所期望的行为。但是,有没有更好的方法来做到这一点,而不是在正则表达式中重复\ d? (想象一下,\ d是一个更复杂的现实生活正则表达式。)

我想抢占某些建议。我很清楚,我可以做这些事情:

  • 使用分割功能,内饰空间,并验证每个元素 反对:

    ^\d$ 
    
  • 一个逗号添加到年底字符串和验证对:

    ^(?:\d\s*,\s*)+$ 
    
  • 去掉逗号和空格和验证对:

    ^\d+$ 
    

我如果有一个速记或更优雅的方式编写正则表达式说只是好奇,“......和处理栅栏柱问题。”

回答

2

可以匹配字符串的开始或像这样

(?!,)((^|\s*,\s*)\d)+$ 

,或者使用非捕获组的分隔符...

(?!,)(?:(?:^|\s*,\s*)\d)+$ 

负先行是确保了第一个字符不是,

它摆脱了第二个\d。虽然它更优雅吗?我想这取决于你。由于\d的简单性,我认为它不在这种情况下,但是如果您有一个非常复杂的表达式而不是\d,它可以清理正则表达式。

另一种方式来避免\d两次将做这样的事情(我使用C#在我的例子):

string complexExpression = @"\d"; // Whatever your actual expression is 
string regex = string.Format(@"^{0}(?:\s*,\s*{0})*$", complexExpression); 

这完全是人为的,所产生的表达当然是一样的,但有人可能会争辩说,它更像这样可读/优雅,而不是100%的正则表达式解决方案。

+0

@trw我编辑了我的答案。您的正则表达式引擎是否支持负向预览? – Vache 2014-09-12 17:40:57

+0

是的,它的确如此。我明白了,因为引擎非常渴望,所以前导逗号仍然会匹配'^ | \ s *,\ s *'。谢谢你的负面看法! – trw 2014-09-12 18:01:42