我需要编写一个正则表达式,它匹配表示逗号分隔星期几的字符串,如:
"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
。我的问题是如何过滤掉匹配此模式的逗号起始字符串。
提前致谢。
答案 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
。
答案 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}}的洒水当然会处理空白。