需要帮助构建一个正则表达式

时间:2011-07-20 08:13:18

标签: regex string regex-negation

我需要编写一个正则表达式,它匹配表示逗号分隔星期几的字符串,如:

"Sun,Mon,Tue,Wed,Thu,Fri,Sat"

每天最多只能出现一次字符串。日期很重要。

到目前为止,我尝试了以下模式:

1)(Sun,|Mon,|Tue,|Wed,|Thu,|Fri,|Sat,)*(Sun|Mon|Tue|Wed|Thu|Fri|Sat)

这个非常糟糕:允许多天存在,也不会看过几天的订单。

2)(Sun)?([,^]Mon)?([,^]Tue)?([,^]Wed)?([,^]Thu)?([,^]Fri)?([,^]Sat)?

这是我到目前为止所做的最好的。这里唯一的问题是它匹配以逗号开头的字符串,例如,Mon,Tue,Fri。我的问题是如何过滤掉匹配此模式的逗号起始字符串。

提前致谢。

4 个答案:

答案 0 :(得分:5)

同意正则表达式可能不是最佳选择。但是,如果您当前版本的唯一问题是它匹配以逗号开头的字符串,您可以在正则表达式的开头处检查一个起始逗号:

(?!,)(Sun)?([,^]Mon)?([,^]Tue)?([,^]Wed)?([,^]Thu)?([,^]Fri)?([,^]Sat)?

但是,我不认为[,^]做你认为它的作用 - 在我熟悉的正则表达式中,方括号内的^与文字^匹配时不是列表中的第一个字符 - 它与字符串的开头不匹配。您可以将其替换为(^|,)

(?!,)(Sun)?((^|,)Mon)?((^|,)Tue)?((^|,)Wed)?((^|,)Thu)?((^|,)Fri)?((^|,)Sat)?

答案 1 :(得分:4)

这有点复杂,但它符合您的所有规格。也许正则表达式不是最好的解决方案......

^(Sun(,(?=.)|$))?(Mon(,(?=.)|$))?(Tue(,(?=.)|$))?(Wed(,(?=.)|$))?(Thu(,(?=.)|$))?(Fri(,(?=.)|$))?(Sat)?$

作为一个冗长的正则表达式:

^         # start of string
(         # Try to match...
 Sun      # Sun
 (        # followed by either
  ,       # a comma
  (?=.)   # but only if more text follows
 |        # or
  $       # end of string
 )
)?        # make it optional.
(Mon(,(?=.)|$))?    # same for Mon-Fri
(Tue(,(?=.)|$))?
(Wed(,(?=.)|$))?
(Thu(,(?=.)|$))?
(Fri(,(?=.)|$))?
(Sat)?    # never a comma after Sat
$         # end of string

答案 2 :(得分:3)

另一种选择是word boundaries的创造性使用:

^\b(?:Sun)?,?\b(?:Mon)?,?\b(?:Tue)?,?\b(?:Wed)?,?\b(?:Thu)?,?\b(?:Fri)?,?\b(?:Sat)?$

或者,如果您不关心每天捕捉,您可以进一步简化:

^\b(Sun)?,?\b(Mon)?,?\b(Tue)?,?\b(Wed)?,?\b(Thu)?,?\b(Fri)?,?\b(Sat)?$

\b仅匹配单词字符和非单词字符。在这种情况下,在一天和逗号之间或字符串的边缘(开始或结束) 单词边界确保每个逗号都被字母包围:它将永远不会匹配字符串边缘附近的逗号。同样,如果逗号不存在,它将永远不会在两天之间匹配,如SunMon

示例:http://rubular.com/r/mTCU0ZWtMm

答案 3 :(得分:1)

(我会将此作为对OpenSauce答案的评论,因为它很大程度上归功于该解决方案,但我没有足够的声誉来发表评论或者不幸的是赞成这个答案。请向我们投票如果你觉得这个答案有用!)

作为原始问题的扩展,如果您想测试字符串是:

  • 以逗号分隔的零列表(空字符串)或从显式小项目集中提取的更多项目
  • 项目可以按任何顺序出现
  • 项目只能出现一次
  • 没有前导或尾随逗号
  • 项目可以用空格包围

然后以下内容对我有用:

^(?!,)((^|,)\s*Mon\s*(?!.*Mon)|(^|,)\s*Tue\s*(?!.*Tue)|(^|,)\s*Wed\s*(?!.*Wed)|(^|,)\s*Thu\s*(?!.*Thu)|(^|,)\s*Fri\s*(?!.*Fri)|(^|,)\s*Sat\s*(?!.*Sat)|(^|,)\s*Sun\s*(?!.*Sun))*$

例如,匹配:

  • ""
  • "星期二,星期四"
  • "星期四,星期二"
  • "星期二,星期二"

此处的诀窍是更改为(Mon | Tue | Wed)*类型模式,以便按任意顺序查找多个匹配项,但随后为每个项添加negative lookahead,例如Mon(?!.*Mon)之后添加Mon意味着"如果您匹配(.*),请确保其后不再运行任何字符Mon,然后再运行\s* {{1}} 1}}",然后来自OpenSauce的一些灵感来回答如何确保只有足够的逗号存在。 {{1}}的洒水当然会处理空白。