检查字符串是否为日期格式 (UNIX)?

Check if string is in date format (UNIX)?

我想检查该变量是否采用正确的日期格式或变量是否为空...如果它采用正确的日期格式那么我将执行某事

我试过:

dada=2015-10-11
if [[ "$dada" = ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]
  then echo "Date $dada is valid  (YYYY-MM-DD)"

  else echo "Date $dada is not invalid format (YYYY-MM-DD)"
fi

还有

 if [ "`date '+%Y-%m-%d' -d $d 2>/dev/null`" = "$dada" ]

    then echo "Date $dada is valid  (YYYY-MM-DD)"

  else echo "Date $dada is not invalid format (YYYY-MM-DD)"
fi

但它似乎总是 return 并告诉我我的格式不正确。

$dada 是一个动态变量,它可以是数字 '444.1' 、日期格式 '2017-11-12' 或字符串 'hello this is not valid'

dada=2015-10-11
date -d $dada > /dev/null 2>&1 
[[ $? -eq 0 ]] && echo ok  ||  echo not ok

将大量评论转化为答案。

您希望进行多彻底的检查?例如,支票应该拒绝 2015-02-29 吗?

2015-02-29 should be also rejected yup!

如果您需要拒绝 2015-02-29,您将需要比单行更多的检查 — 否则单行将非常长且复杂,并且其中会有许多备选方案。


验证数据模式的经典方法是使用来自 case 语句的模式匹配——也许使用这样的东西:

case "$dada" in
([12][0189][0-9][0-9]-[01][0-9]-[0-3][0-9]) : OK;;
(*) : Not OK;;
esac

但可能有更好的现代方法来做到这一点。这主要允许年份 18xy、19xy、20xy、21xy(尽管它也允许通过 10xy、11xy、28xy、29xy);你必须决定这是否明智。同样,它允许通过第 13-19 个月(和 00)和第 32-39 天(和 00);那些是无条件无效的。然后你就剩下“30 days hath September, …”要担心了。

如果删除模式周围的前导 (,该语句将适用于古董和古老的 shell,例如 Bourne shell。它与 Korn shell 无关——它是 POSIX-like shells 和 pre-POSIX shells.[=43 中的标准符号=]

How about just checking if the string format is in place like XXXX-XX-XX?

我展示的 case 命令在 1800 到 2199 的范围内可以正常工作多年。但它是 'old school' 表示法。优点是它有效,我不必阅读手册。测试一下——将 : 命令更改为 echo.

I have tried the case but it seems like the code did not identify my data as a date. Is there any problem with my declaration of dada?

在我的 Mac 上,我能够 运行(逐字 — 单行命令):

ksh -c 'dada=2015-10-11; case "$dada" in ([12][0189][0-9][0-9]-[01][0-9]-[0-3][0-9]) echo OK;; (*) echo Not OK;; esac'

我得到了 OK 作为输出。对于 2215-10-112015-20-11 等值,我得到 Not OK。使用 dada="2015-01-11"; 而不是不带引号的形式会更好,但实际上并不重要。

How about if I were to add a time at the back of the date — 2015-20-11 23:21? Can I write it as 'case "$HELLO" in ([0-3][0-9]/[01][0-9]/[0-9][0-9] [0-2][0-9]:[0-6][0-9])'

您当然可以添加一个匹配时间的 glob 表达式。我不明白为什么你提出的那个可能是正确的,但可以使用其他模式。

例如:

dada="2015-11-20 23:21"
case "$dada" in
([12][0189][0-9][0-9]-[01][0-9]-[0-3][0-9]\ [012][0-9]:[0-5][0-9])
    echo OK;;
(*) echo Not OK;;
esac

请注意,在模式中 space 之前需要反斜杠。当 运行 显示数据时,脚本报告 OK。将 23 更改为 32 并报告 Not OK.

可能有一种方法可以使用 [[ 命令来执行此操作,而不是写出 case 语句。

使用 case 进行更复杂(彻底)的验证可能不是一个好主意。您最好调用一个可以正确验证日期的工具。您可以使用 (GNU) date 命令,或者您可以使用 Perl 或 Python 或其中一种脚本语言。这些将拒绝 2015-02-29 23:21 但允许 2016-02-29 23:21 没有问题。