提问人:Luqman 提问时间:10/12/2023 最后编辑:JL00001Luqman 更新时间:10/13/2023 访问量:63
Bash:IF条件下的日期比较未按预期工作
Bash : Date comparison in IF condition not working as expected
问:
echo "Input start date and time (yyyy-mm-dd hh:mm) :"
read start_date_time
echo "Input end date and time(yyyy-mm-dd hh:mm) :"
read end_date_time
while [[ $(date -d "$start_date_time" +%Y-%m-%d\ %H:%M 2>/dev/null) != $start_date_time || $(date -d "$end_date_time" +%Y-%m-%d\ %H:%M 2>/dev/null) != $end_date_time ]]
do
echo "Invalid input! Please reinsert in the correct format."
echo "Start date and time :"
read start_date_time
echo "End date and time :"
read end_date_time
if [[ $(date -d "$start_date_time" +%s) -gt $(date -d "$end_date_time" +%s) ]]
then
echo "Start datetime cannot be greater than end datetime."
continue
fi
done
此脚本中的条件不起作用,即使 when 大于 .我什至尝试了以下方法,但无济于事:if
echo
$start_date_time
$end_date_time
if [[ $start_date_time > $end_date_time ]]
关于如何解决这个问题,我已经没有想法了。
答:
1赞
Paul Hodges
10/12/2023
#1
正如 John Bollinger 在他的评论中指出的那样,如果你在顶部输入有效的日期时间值,它永远不会进入循环,因此永远不会检查结束大于开始。
如果在开始时输入无效值,它会进入循环并要求输入新值,然后检查 start > end 和 s,但唯一测试的是两个日期是否有效,因此循环会退出,而不会让您重新输入它们。continue
while
此外,您的代码目前允许开始和结束相同而没有抱怨,这可能不是您想要的。
考虑使用函数进行重构以消除冗余代码:
take_datetime() {
local dt= prompt="${1:-Please input a valid date and time(yyyy-mm-dd hh:mm) :}"
read -p "$prompt" dt
until date -d "$dt" "+%Y-%m-%d %H:%M"
do dt=$(take_datetime "$prompt")
done
}
declare -i stst=0 etst=0
until (( etst > stst ))
do ((stst)) && printf "\n *** Ending datetime must be greater than starting datetime ***\n"
start=$( take_datetime "Input START date and time (yyyy-mm-dd hh:mm) : " )
end=$( take_datetime "Input END date and time (yyyy-mm-dd hh:mm) : " )
stst=$( date -d "$start" "+%s" )
etst=$( date -d "$end" "+%s" )
done
echo "START: $start"
echo "END : $end"
这目前允许使用任何有效的日期/时间格式,并将其转换为所需的格式。
$: ./tst
Input START date and time (yyyy-mm-dd hh:mm) : 1234-11-12 11:13
Input END date and time (yyyy-mm-dd hh:mm) : 11/12/1234 11:14
START: 1234-11-12 11:13
END : 1234-11-12 11:14
这确实留下了混淆月份和日期的可能性,例如欧洲与美国的规范。要像以前一样强制输入格式,请更新函数:
take_datetime() {
local dt= prompt="${1:-Please input a valid date and time(yyyy-mm-dd hh:mm) :}"
read -p "$prompt" dt
until date -d "$dt" >/dev/null && [[ $( date -d "$dt" "+%Y-%m-%d %H:%M" ) == "$dt" ]]
do dt=$( take_datetime "Please check your format; $prompt" )
done
echo "$dt"
}
这应该可以做到:
$: ./tst
Input START date and time (yyyy-mm-dd hh:mm) : foo
date: invalid date ‘foo’
Please check your format; Input START date and time (yyyy-mm-dd hh:mm) : 1234-11-12 11:13
Input END date and time (yyyy-mm-dd hh:mm) : 11/12/1234 11:14
Please check your format; Input END date and time (yyyy-mm-dd hh:mm) : 1234-11-12 11:14
START: 1234-11-12 11:13
END : 1234-11-12 11:14
Namerefs 可能会让它更漂亮......
评论
if
if
set -x
if