2

我无法完全理解 ^ 在我的 preg_match 中所做的事情。

 if (preg_match('~^(\d\d\d\d)(-(\d{1,2})(-(\d{1,2}))?)?$~', trim($date), $dateParts)) {
   echo the $dateparts and do some magic with them
 } else {
   tell me the date is formatted wrong
 }

正如我所看到的,这正在查看 $date 是否与我读为 4 位小数 - 1 或 2 位小数 - 1 或 2 位小数的格式相匹配

如果匹配,则 IF 语句显示日期,如果不匹配,则会给出日期格式不正确的错误。

但是,仅将年份 $date = '1977' 传递给它(没有其他日期或月份)它仍然会通过并显示日期部分,我认为它会引发错误?

有人可以指出我在正则表达式中缺少什么吗?我猜它是 ^ 或者最后的 ?$ 可能意味着只匹配它的一部分?

4

4 回答 4

3

没有必要对所有东西进行分组。这看起来更好,并且会做同样的事情:

preg_match('~^\d{4}(-\d{1,2}(-\d{1,2})?)?$~', trim($date), $dateParts)

这也解释了为什么“ 1977”被接受 - 月份和日期部分都是可选的(问号表示可选)。

做你说的(“4 位小数 - 1 或 2 位小数 - 1 或 2 位小数”),您需要删除两个可选组:

preg_match('~^\d{4}-\d{1,2}-\d{1,2}$~', trim($date), $dateParts)

" ^" 和 " $" 与您看到的问题无关。它们只是字符串开头和字符串结尾的锚点,确保检查的字符串中除了模式描述的内容之外没有其他内容。离开他们,"blah 1977-01-01 blah"将开始匹配。

于 2009-07-02T11:31:20.223 回答
2

试试这个:

'~^(\d\d\d\d)-(\d{1,2})-(\d{1,2})$~'

问题是正则表达式允许“?”作为可选的月份和日期。特点。

于 2009-07-02T11:29:48.010 回答
2

^并将$您的模式分别锚定到传入字符串的开头和结尾。这?是一个乘数,匹配前面模式的 0 或 1(在这种情况下,括号中的位)。

你的模式匹配一​​年,或者一年和一个月,或者一年和一个月和一个日期;如果你跟着括号,你会看到 final?在一年后围绕整个模式的括号上运行。

^    # beginning of string
    (\d\d\d\d)   #year
    (
        -(\d{1,2})   #month after a dash
        (
            -(\d{1,2}) #date after a dash
        )? #date optional
    )?   # month and date optional
$   # end of string
于 2009-07-02T11:30:01.117 回答
2

好的,让我们为您分解一下:

  • '~^(\d\d\d\d)(-(\d{1,2})(-(\d{1,2}))?)?$~'
  • ~ - 开头和结尾都是正则表达式分隔符,所以它们并不是正则表达式的一部分。
  • ^ -表示“这是行首”
    • 避免在字符串中间匹配,并锚定它,以便字符串的开头必须匹配
  • (\d\d\d\d) - 匹配(并捕获)四位数字,不是可选的
    • 这也可以写成\d{4}
  • (-(\d{1,2})(-(\d{1,2}))?)?- 匹配(并捕获)一个可选组。
    • 它说如果这个组存在,它必须是一个破折号,后跟一位或两位数(日或月),后跟一个破折号,后跟一位或两位数(日或月)
  • $ - 表示字符串的结尾,因此这与字符串开头的 ^ 一起表示整个字符串必须与正则表达式匹配。

此 Regex 将匹配的一些示例:

  • 1982-08-11
  • 1982-30-01
  • 8127-99-52

一些不匹配的示例:

  • 82-08-11
  • 2009-10

正如你所看到的,这个正则表达式将接受一些不是真正有效日期的“日期”,所以我可能也会通过某种日期处理函数来运行它,比如strtotime

于 2009-07-02T11:33:16.693 回答