所以我想到制作一个 bash 函数,以 hh:mm:ss (24 小时格式)接收时间,并制作一个计时器直到那个时间
有点像一次性闹钟,同时还显示还剩多少时间
我正在考虑使用watch
命令来完成此任务
我对如何执行此操作有一些疑问,
首先,我如何使用 bash 来知道在某个时间之前还剩下多少?
那么如何将其转换为人类可读的格式以回显到屏幕上?
另外,我怎样才能在过去或将来的另一天执行此操作?
请帮助我创建这个函数,我将在这里发布最终结果,以便每个人都可以使用它。
编辑:我设法从关联@terdon 发布
timer ()
{
start="$(date +%s -d $1)";
while [ "$start" -ge $(date +%s) ]; do
days="$(($(($(( $start - $(date +%s) )) * 1 )) / 86400))";
time="$(( $start - `date +%s` ))";
if [ $days -gt 0 ]; then
printf '%s day(s) and %s\r' "$days" "$(date -u -d "@$time" +%H:%M:%S)";
else
printf '%s\r' "$(date -u -d "@$time" +%H:%M:%S)";
fi;
sleep 0.1;
done
}
我遇到了一个问题,即使所有参数都在引号内, date -d $1 也无法接受多字参数。我使用 ubuntu 并且使用 bash,这是我运行来进行测试的代码。正如你所看到的,它会忽略第一个单词后面的内容,不带引号,而带引号时,它会给出错误。
$ timer 17:25
00:04:37
$ timer sun
1 day(s) and 06:39:31
$ timer sun 17:25
1 day(s) and 06:39:20
$ timer sun 22:25
1 day(s) and 06:39:09
$ timer "sun 22:25"
date: extra operand ‘22:25’
Try 'date --help' for more information.
bash: [: : integer expression expected
答案1
使用 -d 选项时,您似乎遇到了将多字参数传递给 date 命令的问题。要解决此问题,您可以使用 IFS(内部字段分隔符)变量临时更改 shell 在解析参数时使用的分隔符。以下是如何修改函数以处理多字参数的示例:
timer ()
{
IFS=":" read -ra time_parts <<< "$1"
time_str=""
for part in "${time_parts[@]}"; do
time_str+=" $part"
done
start="$(date +%s -d "$time_str")";
while [ "$start" -ge $(date +%s) ]; do
days="$(($(($(( $start - $(date +%s) )) * 1 )) / 86400))";
time="$(( $start - `date +%s` ))";
if [ $days -gt 0 ]; then
printf '%s day(s) and %s\r' "$days" "$(date -u -d "@$time" +%H:%M:%S)";
else
printf '%s\r' "$(date -u -d "@$time" +%H:%M:%S)";
fi;
sleep 0.1;
done
}
这应该允许您将多字参数传递给函数,例如“sun 22:25”,并让 date 命令正确解析它们。
关于您问的其他问题,您可以使用命令 date -d 来了解距离某个时间还剩多少时间,然后使用该命令
日期 -u -d "@$time" +%H:%M:%S
将其转换为人类可读的格式。
如果您想在过去或将来的另一天执行此操作,您也可以添加日期,例如
日期 -u -d "2022-12-25 22:25" +%s
这将为您提供您提供的日期和时间的时间戳。