如何在 bash 中创建秒表?
How can I create a stopwatch in bash?
我创建了一个简单的秒表(bash 函数)来计时,但现在它以毫秒显示当前时间。
代码:
function stopwatch() {
date +%H:%M:%S:%N
while true; do echo -ne "`date +%H:%M:%S:%N`\r"; done;
}
我尝试按照 this answer 中的说明对其进行更改,但它仅适用于自 Unix Epoch 以来的第二个。
当我使用 date
格式 +%s.%N
时,上述答案的减法停止工作,因为 bash 减法只需要整数。
我怎样才能解决这个问题并拥有一个像这样打印时间的终端秒表:
0.000000000
0.123123123
0.435345345
(and so on..)
?
对于减法,您应该使用 bc
(An arbitrary precision calculator language
)。
这是满足您要求的示例代码:
function stopwatch() {
date1=`date +%s.%N`
while true; do
curr_date=`date +%s.%N`
subtr=`echo "$curr_date - $date1" | bc`
echo -ne "$subtr\r";
sleep 0.03
done;
}
添加了额外的 sleep
以降低 CPU 使用率(在我的机器上没有它几乎是 15% 而有了这个 sleep
它降低到 1%)。
一个可以工作一天的可能(和 hacky)机制:
$ now=$(date +%s)sec
$ while true; do
printf "%s\r" $(TZ=UTC date --date now-$now +%H:%M:%S.%N)
sleep 0.1
done
奖励:您可以随时按回车键获得 LAP 圈数。 ;-)
注意:这是一个快速修复。应该有更好的解决方案...
基于 watch
的变体(相同逻辑):
$ now=$(date +%s)sec; watch -n0.1 -p TZ=UTC date --date now-$now +%H:%M:%S.%N
这是我刚才抓到的一个更好的函数:
function stopwatch() {
local BEGIN=$(date +%s)
echo Starting Stopwatch...
while true; do
local NOW=$(date +%s)
local DIFF=$(($NOW - $BEGIN))
local MINS=$(($DIFF / 60))
local SECS=$(($DIFF % 60))
local HOURS=$(($DIFF / 3600))
local DAYS=$(($DIFF / 86400))
printf "\r%3d Days, %02d:%02d:%02d" $DAYS $HOURS $MINS $SECS
sleep 0.5
done
}
如果您想要像传统秒表一样包含分钟、秒和厘秒的简单内容,您可以使用 sw。
安装
wget -q -O - http://git.io/sinister | sh -s -- -u https://raw.githubusercontent.com/coryfklein/sw/master/sw
用法
# start a stopwatch from 0, save start time in ~/.sw
sw
# resume the last run stopwatch
sw --resume
function stopwatch() {
local BEGIN=$(date +%s)
while true; do
local NOW=$(date +%s)
local DIFF=$(($NOW - $BEGIN))
local MINS=$(($DIFF / 60 % 60))
local SECS=$(($DIFF % 60))
local HOURS=$(($DIFF / 3600 % 24))
local DAYS=$(($DIFF / 86400))
local DAYS_UNIT
[ "$DAYS" == 1 ] && DAYS_UNIT="Day" || DAYS_UNIT="Days"
printf "\r %d %s, %02d:%02d:%02d " $DAYS $DAYS_UNIT $HOURS $MINS $SECS
sleep 0.25
done
}
对于不熟悉的人:在英语中,只有在 1
时才使用单数 -- Day。 0, 2, 3, 4, 5...时,我们用复数
"Days",所以注意是0 Days
.
这是我的:
time cat
你按 Ctrl-c 或 Ctrl-d 停止并显示时间。第一个数字是时间。
我将其进一步细化为这个 bash 别名
alias stopwatch="echo Press Ctrl-c to stop the timer; TIMEFORMAT=%R; time cat; unset TIMEFORMAT"
这是另一个 bash 秒表,借鉴了该线程中的其他答案。此版本与其他版本的不同之处包括:
- 这个版本使用 bash 算术而不是调用
bc
我发现(通过计时)要少 cpu 时间。
- 我已经解决了有人指出的第 25 小时限制,方法是将 24 小时添加到小时部分,即过去的每一天。 (所以现在我猜这是 ~31 天的限制。)
- 我将光标留在输出的右侧,这与接受的答案中的版本不同。这样你就可以轻松地测量圈数(或者更一般地标记重要的事件时间)只需按回车键,这会将计时器移动到下一行,让按键时间可见。
#!/bin/bash
start_time=$(date +%s)
while true; do
current_time=$(date +%s)
seconds_elapsed=$(( $current_time - $start_time ))
timestamp=$(date -d"@$seconds_elapsed" -u +%-d:%-H:%-M:%-S)
IFS=':' read -r day hour minute second <<< "$timestamp"
hour="$(( $hour+24*($day-1) ))"
printf "\r%02d:%02d:%02d" $hour $minute $second
sleep 0.5
done;
这是 运行 stopwatch
的示例输出(作为 PATH 中的可执行脚本)并在第 7 秒和第 18 秒按下 return 键,然后按下 Ctrl-C约9分钟后:
$ stopwatch
00:00:07
00:00:18
00:09:03^C
$
备注:
- 我对日期使用
+%-d:%-H:%-M:%-S
输出格式(这个破折号表示 "leave off any leading zero please"),因为 printf 似乎将带有前导零的数字字符串解释为八进制,并最终抱怨无效值。
- 我去掉纳秒只是因为出于我的目的我不需要超过 1 秒的精度。因此,我将
sleep
持续时间调整得更长以节省计算量。
我创建了一个简单的秒表(bash 函数)来计时,但现在它以毫秒显示当前时间。
代码:
function stopwatch() {
date +%H:%M:%S:%N
while true; do echo -ne "`date +%H:%M:%S:%N`\r"; done;
}
我尝试按照 this answer 中的说明对其进行更改,但它仅适用于自 Unix Epoch 以来的第二个。
当我使用 date
格式 +%s.%N
时,上述答案的减法停止工作,因为 bash 减法只需要整数。
我怎样才能解决这个问题并拥有一个像这样打印时间的终端秒表:
0.000000000
0.123123123
0.435345345
(and so on..)
?
对于减法,您应该使用 bc
(An arbitrary precision calculator language
)。
这是满足您要求的示例代码:
function stopwatch() {
date1=`date +%s.%N`
while true; do
curr_date=`date +%s.%N`
subtr=`echo "$curr_date - $date1" | bc`
echo -ne "$subtr\r";
sleep 0.03
done;
}
添加了额外的 sleep
以降低 CPU 使用率(在我的机器上没有它几乎是 15% 而有了这个 sleep
它降低到 1%)。
一个可以工作一天的可能(和 hacky)机制:
$ now=$(date +%s)sec
$ while true; do
printf "%s\r" $(TZ=UTC date --date now-$now +%H:%M:%S.%N)
sleep 0.1
done
奖励:您可以随时按回车键获得 LAP 圈数。 ;-)
注意:这是一个快速修复。应该有更好的解决方案...
基于watch
的变体(相同逻辑):
$ now=$(date +%s)sec; watch -n0.1 -p TZ=UTC date --date now-$now +%H:%M:%S.%N
这是我刚才抓到的一个更好的函数:
function stopwatch() {
local BEGIN=$(date +%s)
echo Starting Stopwatch...
while true; do
local NOW=$(date +%s)
local DIFF=$(($NOW - $BEGIN))
local MINS=$(($DIFF / 60))
local SECS=$(($DIFF % 60))
local HOURS=$(($DIFF / 3600))
local DAYS=$(($DIFF / 86400))
printf "\r%3d Days, %02d:%02d:%02d" $DAYS $HOURS $MINS $SECS
sleep 0.5
done
}
如果您想要像传统秒表一样包含分钟、秒和厘秒的简单内容,您可以使用 sw。
安装
wget -q -O - http://git.io/sinister | sh -s -- -u https://raw.githubusercontent.com/coryfklein/sw/master/sw
用法
# start a stopwatch from 0, save start time in ~/.sw
sw
# resume the last run stopwatch
sw --resume
function stopwatch() {
local BEGIN=$(date +%s)
while true; do
local NOW=$(date +%s)
local DIFF=$(($NOW - $BEGIN))
local MINS=$(($DIFF / 60 % 60))
local SECS=$(($DIFF % 60))
local HOURS=$(($DIFF / 3600 % 24))
local DAYS=$(($DIFF / 86400))
local DAYS_UNIT
[ "$DAYS" == 1 ] && DAYS_UNIT="Day" || DAYS_UNIT="Days"
printf "\r %d %s, %02d:%02d:%02d " $DAYS $DAYS_UNIT $HOURS $MINS $SECS
sleep 0.25
done
}
对于不熟悉的人:在英语中,只有在 1
时才使用单数 -- Day。 0, 2, 3, 4, 5...时,我们用复数
"Days",所以注意是0 Days
.
这是我的:
time cat
你按 Ctrl-c 或 Ctrl-d 停止并显示时间。第一个数字是时间。
我将其进一步细化为这个 bash 别名
alias stopwatch="echo Press Ctrl-c to stop the timer; TIMEFORMAT=%R; time cat; unset TIMEFORMAT"
这是另一个 bash 秒表,借鉴了该线程中的其他答案。此版本与其他版本的不同之处包括:
- 这个版本使用 bash 算术而不是调用
bc
我发现(通过计时)要少 cpu 时间。 - 我已经解决了有人指出的第 25 小时限制,方法是将 24 小时添加到小时部分,即过去的每一天。 (所以现在我猜这是 ~31 天的限制。)
- 我将光标留在输出的右侧,这与接受的答案中的版本不同。这样你就可以轻松地测量圈数(或者更一般地标记重要的事件时间)只需按回车键,这会将计时器移动到下一行,让按键时间可见。
#!/bin/bash
start_time=$(date +%s)
while true; do
current_time=$(date +%s)
seconds_elapsed=$(( $current_time - $start_time ))
timestamp=$(date -d"@$seconds_elapsed" -u +%-d:%-H:%-M:%-S)
IFS=':' read -r day hour minute second <<< "$timestamp"
hour="$(( $hour+24*($day-1) ))"
printf "\r%02d:%02d:%02d" $hour $minute $second
sleep 0.5
done;
这是 运行 stopwatch
的示例输出(作为 PATH 中的可执行脚本)并在第 7 秒和第 18 秒按下 return 键,然后按下 Ctrl-C约9分钟后:
$ stopwatch
00:00:07
00:00:18
00:09:03^C
$
备注:
- 我对日期使用
+%-d:%-H:%-M:%-S
输出格式(这个破折号表示 "leave off any leading zero please"),因为 printf 似乎将带有前导零的数字字符串解释为八进制,并最终抱怨无效值。 - 我去掉纳秒只是因为出于我的目的我不需要超过 1 秒的精度。因此,我将
sleep
持续时间调整得更长以节省计算量。