首页 > 解决方案 > RegEx 日期模式格式验证未按预期工作

问题描述

我正在尝试验证日期格式输入。输入不是实际日期,而是D M Y输入。而且我不想验证实际日期!只是格式。

我想用或分隔符评估任何使用 double D、 double M、 double 或 quadruple完成的输入。Y-_

我当前的 RegEx 如下所示: ^(?=.*[mM]{2})(?=.*[dD]{2})(?=.*[yY]{2,4})(?=.*[-_]{0,2}).*$

但是,即使找到的字符多于预期字符,这也会评估为真。限制器{2}似乎没有效果。

例如:mmddyyyymmmmmm即使那里有多个m,也会评估为真。我不明白。

预期的结果是只有如下组合才能测试为真:

dd-mm-yy
MM-DD_YYYY
yyyy_dd-MM
mmddyy
YYYYddMM

而不是这样的:

ddyyyyymmmmmmmmm
mmddyymm

请帮我纠正我的正则表达式。

标签: regex

解决方案


通常,匹配一个只能匹配包含允许块的字符串的字符串是有意义的,然后使用一些编程手段来完成其余的“计数”工作(您只需检查有多少mm,ddyyyy/ 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:动态方法

这种方法意味着匹配仅由三个DMY块组成的字符串,并使用正向前瞻来限制模式,这将要求字符串仅包含每个块的一次出现。瓶颈和问题在于块是多字符串,因此您需要使用经过调和的贪婪令牌(或打开它,使正则表达式更加怪异):

^
  (?=(?:(?![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 次,因此,字符串可以包含 3 次出现dym,即使它们相同(mmmmmm也将匹配)。前瞻的形式都是(?=(?:(?!BLOCK).)*BLOCK(?:(?!BLOCK).)*$)- 仅当存在除 BLOCK 之外的任何文本时才匹配,然后是 BLOCK,然后是除 BLOCK 之外的任何文本,直到字符串的末尾。


推荐阅读