【问题标题】:Check if string is in date format (UNIX)?检查字符串是否为日期格式(UNIX)?
【发布时间】:2017-05-22 05:50:04
【问题描述】:

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

我试过了:

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

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

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

【问题讨论】:

  • 您希望进行多彻底的检查?例如,支票是否应该拒绝2015-02-29?经典的方法是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 个月和第 32-39 天;那些是无条件无效的。然后你就剩下“9 月还有 30 天……”要担心。
  • 2015-02-29 也应该被拒绝是的! @JonathanLeffler
  • 如果您需要拒绝2015-02-29,您将需要比单行更多的检查 - 否则单行将非常长且复杂,并且其中会有很多替代方案。
  • @JonathanLeffler 我明白了,如何检查字符串格式是否像 XXXX-XX-XX 一样到位?我拥有的当前代码返回“无效回声”
  • 我展示的 case 命令在 1800 到 2199 年的范围内做了合理的工作。但它是“老派”符号。优点是它有效,我不必阅读手册。测试一下——把:命令改成echo

标签: shell unix ksh


【解决方案1】:

将大量 cmets 转换为答案。

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

2015-02-29 也应该被拒绝是的!

如果您需要拒绝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, …”需要担心了。

如果您删除了模式周围的前导 (,则该语句将适用于古董和古老的贝壳,例如 Bourne 贝壳。它与 Korn shell 无关——它是 POSIX-like shell 和 pre-POSIX shell 中的标准表示法。

只检查字符串格式是否像 XXXX-XX-XX 这样就位如何?

我展示的 case 命令在 1800 到 2199 年的范围内执行了合理的工作。但它是“老派”表示法。优点是它有效,我不必阅读手册。测试一下——把:命令改成echo

我已经尝试过这种情况,但似乎代码没有将我的数据识别为日期。我的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"; 代替不带引号的形式会更好,但实际上并不重要。

如果我要在日期后面添加一个时间——2015-20-11 23:21,怎么样?我可以写成'case "$HELLO" in ([0-3][0-9]/[01][0-9]/[0-9][0-9] [0-2][0-9]:[0-6][0-9])'

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

例如:

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

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

可能有一种方法可以使用[[ 命令而不是写出case 语句。

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

【讨论】:

    【解决方案2】:
    dada=2015-10-11
    date -d $dada > /dev/null 2>&1 
    [[ $? -eq 0 ]] && echo ok  ||  echo not ok
    

    【讨论】:

      猜你喜欢
      • 2011-10-06
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 2020-06-23
      • 2011-11-18
      • 1970-01-01
      • 2021-03-14
      • 2018-06-15
      相关资源
      最近更新 更多