我正在尝试验证日期格式输入。输入的不是实际日期,而是D
M
Y
输入。我不想要验证实际日期!只是格式。
我想评估使用双D
或M
分频器进行双Y
,双-
,双{或四倍_
完成的任何输入。
我当前的RegEx看起来如下:
^(?=.*[mM]{2})(?=.*[dD]{2})(?=.*[yY]{2,4})(?=.*[-_]{0,2}).*$
但是,即使找到的字符多于预期字符,它的计算结果也为true。限制器{2}
似乎无效。
例如:mmddyyyymmmmmm
将评估为true,即使其中有多个m
。我不明白。
预期结果是只有诸如以下的组合才能测试为真:
dd-mm-yy
MM-DD_YYYY
yyyy_dd-MM
mmddyy
YYYYddMM
而不是类似的东西
ddyyyyymmmmmmmmm
mmddyymm
请帮助我更正RegEx。
答案 0 :(得分:2)
通常,匹配一个只能匹配包含允许块的字符串的字符串,然后使用某种编程方法来完成其余的“计数”工作(您只需检查有多少mm
,{ {1}}或dd
/ yyyy
)。
如果必须使用正则表达式,则有两种方法。
解决方案1:枚举所有替代方案
这是最不舒适,不是动态/不可扩展的解决方案,您只需将所有可能的模式收集到一个组中即可
yy
请参见this issue in the SAM repo。 ^(?:
[dD]{2}[_-]?[mM]{2}[_-]?[yY]{2}(?:[yY]{2})? |
[mM]{2}[_-]?[dD]{2}[_-]?[yY]{2}(?:[yY]{2})? |
[mM]{2}[_-]?[yY]{2}(?:[yY]{2})?[_-]?[dD]{2} |
[dD]{2}[_-]?[yY]{2}(?:[yY]{2})?[_-]?[mM]{2} |
[yY]{2}(?:[yY]{2})?[_-]?[dD]{2}[_-]?[mM]{2} |
[yY]{2}(?:[yY]{2})?[_-]?[mM]{2}[_-]?[dD]{2}
)$
断言字符串开头的位置,^
非捕获组及其他选项,(?:...|...)
断言字符串的结尾。
解决方案2:动态方法
此方法意味着匹配仅由三个$
,D
或M
块组成的字符串,并使用正向先行限制模式,该正向先行将要求字符串仅包含单个每个块的发生。瓶颈和问题在于,这些块是多字符字符串,因此您需要使用regex demo(或将其解包,使正则表达式更加怪异):
Y
因此,这里的^
(?=(?:(?![mM]{2}).)*[mM]{2}(?:(?![mM]{2}).)*$)
(?=(?:(?![dD]{2}).)*[dD]{2}(?:(?![dD]{2}).)*$)
(?=(?:(?![yY]{2}(?:[yY]{2})?).)*[yY]{2}(?:[yY]{2})?(?:(?![yY]{2}(?:[yY]{2})?).)*$)
(?:
(?:[mM]{2}|[dD]{2}|[yY]{2}(?:[yY]{2})?)
(?:[_-](?!$))?
){3}
$
部分从头到尾重复了3次,因此该字符串可以包含(?:[mM]{2}|[dD]{2}|[yY]{2}(?:[yY]{2})?)(?:[_-](?!$))?
,d
或y
的三个出现,甚至如果它们相同(m
也将匹配)。前瞻全部为mmmmmm
的形式-仅当存在除BLOCK之外的任何文本,然后是BLOCK以及然后除BLOCK之外的任何文本为止,才匹配,直到字符串的结尾。