PHP 正则表达式非捕获不匹配组

2022-08-31 00:13:07

我正在制作一个日期匹配正则表达式,一切都很顺利,到目前为止,我已经得到了这个:

"/(?:[0-3])?[0-9]-(?:[0-1])?[0-9]-(?:20)[0-1][0-9]/"

它将(希望)匹配21世纪的一位数或两位数的日期和月份,以及两位数或四位数的年份。一些尝试和错误使我走到了这一步。

但是,关于这些结果,我有两个简单的问题:

  1. (?: )对此的简单解释是什么?显然,这是一个不匹配的组。但后来...

  2. 尾随的用途是什么?例如:?(? )?


答案 1

[再次编辑以改善格式并修复简介。

这是一个评论和答案。

答案部分...我同意亚历克斯之前的回答。

  1. (?: ),与 相反,用于避免捕获文本,通常是为了减少与您想要的引用一起抛出的反向引用或提高速度性能。( )

  2. 这?跟在 后面 - 或者当跟随除 或 以外的任何内容时 - 意味着前面的项目可能在合法匹配项中找到,也可能找不到。例如,将匹配z3和z34,但它不匹配z35或z等。(?: )* + ?{}/z34?/

注释部分...我对您正在处理的正则表达式进行了可能被认为是改进的内容:

(?:^|\s)(0?[1-9]|[1-2][0-9]|30|31)-(0?[1-9]|10|11|12)-((?:20)?[0-9][0-9])(?:\s|$)

-- 首先,它避免了像0-0-2011这样的事情

-- 其次,它避免了像233443-4-201154564这样的事情

- 第三,它包括1-1-2022之类的东西

- 第四,它包括像1-1-11这样的东西

-- 第五,它避免了像34-4-11这样的事情

- 第六,它允许您捕获日,月和年,以便您可以更轻松地在代码中引用它们。例如,将执行进一步检查的代码(是第二个捕获的组 2,并且是第一个捕获的组 29,这是闰年,否则第一个捕获的组<29),以查看 2 月 29 日的日期是否合格。

最后,请注意,您仍然会得到不存在的日期,例如,31-6-11。如果您想避免这些,请尝试:

(?:^|\s)(?:(?:(0?[1-9]|[1-2][0-9]|30|31)-(0?[13578]|10|12))|(?:(0?[1-9]|[1-2][0-9]|30)-(0?[469]|11))|(?:(0?[1-9]|[1-2][0-9])-(0?2)))-((?:20)?[0-9][0-9])(?:\s|$)

另外,我假设日期之前和后面会有一个空格(或乞求/行尾),但你可能想要调整它(例如,允许标点符号)。

其他地方的评论者引用了这个资源,你可能会发现它很有用:http://rubular.com/


答案 2
  1. 它是一个非捕获组。您不能反向引用它。通常用于整理反向引用和/或提高性能。
  2. 这意味着上一个捕获组是可选的。

推荐