我正在尝试验证日期格式输入。输入不是实际日期,而是D
M
Y
输入。而且我不想验证实际日期!只是格式。
我想评估使用双D
、双M
、双Y
-
或_
除法器完成的任何输入。
我当前的正则表达式如下所示:^(?=.*[mM]{2})(?=.*[dD]{2})(?=.*[yY]{2,4})(?=.*[-_]{0,2}).*$
但是,即使找到的字符超过预期字符,这也为真。限制器似乎{2}
没有效果。
例如:即使有多个m
,mmddyyyymmmmmm
也会评估 true。 我不明白。
预期结果是,只有以下组合才能测试 true:
dd-mm-yy
MM-DD_YYYY
yyyy_dd-MM
mmddyy
YYYYddMM
而不是像这样的东西:
ddyyyyymmmmmmmmm
mmddyymm
请帮助我更正我的正则表达式。
通常,匹配一个只能匹配包含允许块的字符串的字符串,然后使用一些编程方法来完成其余的"计数"工作是有意义的(你只需检查有多少mm
,dd
,或yyyy
/yy
(。
如果必须使用正则表达式,有两种方法。
解决方案#1:枚举所有备选方案
这是最不舒服,不是动态/不可扩展的解决方案,您只需在单个组中收集所有可能的模式:
^(?:
[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
或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}
$
查看正则表达式演示
所以,在这里,(?:[mM]{2}|[dD]{2}|[yY]{2}(?:[yY]{2})?)(?:[_-](?!$))?
部分从头到尾重复 3 次,所以,字符串可以包含三次出现的d
、y
或m
,即使它们是相同的(mmmmmm
也会匹配(。前瞻都是(?=(?:(?!BLOCK).)*BLOCK(?:(?!BLOCK).)*$)
的形式 - 仅当有任何文本但 BLOCK 时匹配,然后是 BLOCK,然后是除 BLOCK 之外的任何文本,直到字符串的末尾。