当 ISO 8601 日期格式的值都位于同一时区时(示例中的 Z 代表 Zulu 或 UTC),可以将它们作为字符串进行比较;这是该格式的主要优点之一。
问题在于if [ "${date3}" < "${date1}" ]
表示法是您在测试过程中进行输入重定向 - 这不是您想要的。
如果你有 Bash,你可以使用[[
代替[
:
if [[ "${date3}" < "${date1}" ]]
或者,您的test
(or [
) 命令可以接受:
if [ "${date3}" '<' "${date1}" ]
比较周围的引号可防止将其解释为 I/O 重定向。
(这适用于 Mac OS X 10.9.4,但这是使用bash
再次。然而,/bin/[
也接受它,只要我省略尾随]
— 一定是因为它没有被调用为[
它需要不存在]
.) POSIXtest http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html不需要支持>
or <
作为运营商——仅=
and !=
需要进行字符串比较。
该任务的经典命令是expr http://pubs.opengroup.org/onlinepubs/9699919799/utilities/expr.html:
if [ $(expr "${date3}" '<' "${date1}") == 1 ]
这可能是最可移植的机制(第七版 Unix 有expr
对于这个任务)。这也是最笨拙的表示法。
更新的问题
我不清楚你的日期表达式本身有什么问题,但事实上它们给了你date: invalid date '2014-09-03T04:27:23Z'
错误表明版本date
您可用的不支持该符号。它在 Ubuntu 14.04 上运行正常,版本为date --version
开始date (GNU coreutils) 8.21
。这是一个运行时对我有用的脚本bash
(但不是当运行时sh
——因为在 Ubuntu 上这是一个符号链接dash
而不是bash
)。我用的是-u
(UTC) 选项,以便输入和输出时间一致——小心可怕的时区。
请注意,如果您使用的是 GNUdate
,您可以指定+%s
获取自纪元(即 1970-01-01 00:00:00 +00:00)以来的时间值(以秒为单位)作为纯数字,并且可以对它们进行数字比较。
dtcmp.sh
date1=`date -u -d "2014-09-03T04:27:23Z" +"%Y-%m-%dT%TZ"`
date2=`date -u -d "2014-09-03T02:23:09Z" +"%Y-%m-%dT%TZ"`
date3=`date -u -d "2014-09-03T05:23:09Z" +"%Y-%m-%dT%TZ"`
if [ ${date3} -lt ${date1} ]
then echo "true (claim: [ $date3 -lt $date1 ])"
else echo "false (claim: [ $date3 -lt $date1 ])"
fi
if [ ${date2} -gt ${date1} ]
then echo "true (claim: [ $date2 -gt $date1 ])"
else echo "false (claim: [ $date2 -gt $date1 ])"
fi
if [ ${date3} '<' ${date1} ]
then echo "true (claim: [ $date3 '<' $date1 ])"
else echo "false (claim: [ $date3 '<' $date1 ])"
fi
if [ ${date2} '>' ${date1} ]
then echo "true (claim: [ $date2 '>' $date1 ])"
else echo "false (claim: [ $date2 '>' $date1 ])"
fi
if [[ ${date3} < ${date1} ]]
then echo "true (claim: [[ $date3 < $date1 ]])"
else echo "false (claim: [[ $date3 < $date1 ]])"
fi
if [[ ${date2} > ${date1} ]]
then echo "true (claim: [[ $date3 > $date1 ]])"
else echo "false (claim: [[ $date3 > $date1 ]])"
fi
if [ $(expr ${date3} '>' ${date1}) = 1 ]
then echo "true (claim: [ \$(expr $date3 '>' $date1) = 1 ])"
else echo "false (claim: [ \$(expr $date3 '>' $date1) = 1 ])"
fi
if [ $(expr ${date2} '>' ${date1}) = 1 ]
then echo "true (claim: [ \$(expr $date2 '>'$date1) = 1 ])"
else echo "false (claim: [ \$(expr $date2 '>' $date1) = 1 ])"
fi
输出示例
bash
$ bash dtcmp.sh
dtcmp.sh: line 6: [: 2014-09-03T05:23:09Z: integer expression expected
false (claim: [ 2014-09-03T05:23:09Z -lt 2014-09-03T04:27:23Z ])
dtcmp.sh: line 11: [: 2014-09-03T02:23:09Z: integer expression expected
false (claim: [ 2014-09-03T02:23:09Z -gt 2014-09-03T04:27:23Z ])
false (claim: [ 2014-09-03T05:23:09Z '<' 2014-09-03T04:27:23Z ])
false (claim: [ 2014-09-03T02:23:09Z '>' 2014-09-03T04:27:23Z ])
false (claim: [[ 2014-09-03T05:23:09Z < 2014-09-03T04:27:23Z ]])
false (claim: [[ 2014-09-03T05:23:09Z > 2014-09-03T04:27:23Z ]])
true (claim: [ $(expr 2014-09-03T05:23:09Z '>' 2014-09-03T04:27:23Z) = 1 ])
false (claim: [ $(expr 2014-09-03T02:23:09Z '>' 2014-09-03T04:27:23Z) = 1 ])
$
dash
$ dash dtcmp.sh
dtcmp.sh: 6: [: Illegal number: 2014-09-03T05:23:09Z
false (claim: [ 2014-09-03T05:23:09Z -lt 2014-09-03T04:27:23Z ])
dtcmp.sh: 11: [: Illegal number: 2014-09-03T02:23:09Z
false (claim: [ 2014-09-03T02:23:09Z -gt 2014-09-03T04:27:23Z ])
false (claim: [ 2014-09-03T05:23:09Z '<' 2014-09-03T04:27:23Z ])
false (claim: [ 2014-09-03T02:23:09Z '>' 2014-09-03T04:27:23Z ])
dtcmp.sh: 26: dtcmp.sh: [[: not found
false (claim: [[ 2014-09-03T05:23:09Z < 2014-09-03T04:27:23Z ]])
dtcmp.sh: 31: dtcmp.sh: [[: not found
false (claim: [[ 2014-09-03T05:23:09Z > 2014-09-03T04:27:23Z ]])
true (claim: [ $(expr 2014-09-03T05:23:09Z '>' 2014-09-03T04:27:23Z) = 1 ])
false (claim: [ $(expr 2014-09-03T02:23:09Z '>' 2014-09-03T04:27:23Z) = 1 ])
$
ksh
$ ksh dtcmp.sh
dtcmp.sh[6]: [: 2014-09-03T05:23:09Z: arithmetic syntax error
false (claim: [ 2014-09-03T05:23:09Z -lt 2014-09-03T04:27:23Z ])
dtcmp.sh[11]: [: 2014-09-03T02:23:09Z: arithmetic syntax error
false (claim: [ 2014-09-03T02:23:09Z -gt 2014-09-03T04:27:23Z ])
dtcmp.sh[16]: [: <: unknown operator
false (claim: [ 2014-09-03T05:23:09Z '<' 2014-09-03T04:27:23Z ])
false (claim: [ 2014-09-03T02:23:09Z '>' 2014-09-03T04:27:23Z ])
false (claim: [[ 2014-09-03T05:23:09Z < 2014-09-03T04:27:23Z ]])
false (claim: [[ 2014-09-03T05:23:09Z > 2014-09-03T04:27:23Z ]])
true (claim: [ $(expr 2014-09-03T05:23:09Z '>' 2014-09-03T04:27:23Z) = 1 ])
false (claim: [ $(expr 2014-09-03T02:23:09Z '>' 2014-09-03T04:27:23Z) = 1 ])
$
zsh
$ zsh dtcmp.sh
dtcmp.sh:[:6: integer expression expected: 2014-09-03T05:23:09Z
false (claim: [ 2014-09-03T05:23:09Z -lt 2014-09-03T04:27:23Z ])
dtcmp.sh:[:11: integer expression expected: 2014-09-03T02:23:09Z
false (claim: [ 2014-09-03T02:23:09Z -gt 2014-09-03T04:27:23Z ])
dtcmp.sh:16: condition expected: <
false (claim: [ 2014-09-03T05:23:09Z '<' 2014-09-03T04:27:23Z ])
dtcmp.sh:21: condition expected: >
false (claim: [ 2014-09-03T02:23:09Z '>' 2014-09-03T04:27:23Z ])
false (claim: [[ 2014-09-03T05:23:09Z < 2014-09-03T04:27:23Z ]])
false (claim: [[ 2014-09-03T05:23:09Z > 2014-09-03T04:27:23Z ]])
true (claim: [ $(expr 2014-09-03T05:23:09Z '>' 2014-09-03T04:27:23Z) = 1 ])
false (claim: [ $(expr 2014-09-03T02:23:09Z '>' 2014-09-03T04:27:23Z) = 1 ])
$
Summary
- shell 都同意 ISO 8601 日期字符串的纯数字比较不起作用。
- Only
bash
接受并正确使用'<'
and '>'
简单的运算符test
aka [
— 其他 shell 要么不接受它,要么接受它但产生错误的答案(这更糟糕!)。
- 对于支持的 shell
[[
,结果一致且正确。
- 所有 shell 都可以正常工作
expr
符号。
为了获得最大的便携性,请使用expr
。为了获得最大的理智,请使用[[
.