14

我创建了一个简单的秒表(bash 函数)来计算时间,但现在它以毫秒为单位显示当前时间。

编码:

function stopwatch() {
    date +%H:%M:%S:%N
    while true; do echo -ne "`date +%H:%M:%S:%N`\r"; done;
}

我尝试按照此答案中的说明进行更改,但它仅适用于自 Unix Epoch 以来的第二个。

当我使用date格式+%s.%N时,由于 bash 减法只需要整数,因此上述答案的减法停止工作。

我该如何解决它并拥有一个可以打印时间的终端秒表,如下所示:

0.000000000
0.123123123
0.435345345
(and so on..)

?

4

7 回答 7

16

一种可以工作一天的可能(和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

奖励:您可以随时按 Enter 键获取LAP时间。;-)

注意:这是一个快速修复。应该有更好的解决方案......

watch基于变体(相同的逻辑):

$ now=$(date +%s)sec; watch -n0.1 -p TZ=UTC date --date now-$now +%H:%M:%S.%N
于 2016-06-23T09:01:56.873 回答
15

如果你想要一些简单的东西,包括分钟、秒和厘秒,比如传统的秒表,你可以使用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 
于 2017-06-23T21:14:44.530 回答
8

这是我的:

time cat

您按Ctrl-cCtrl-d停止并显示时间。第一个数字是时间。

我已将其进一步细化为这个 bash 别名

alias stopwatch="echo Press Ctrl-c to stop the timer; TIMEFORMAT=%R; time cat; unset TIMEFORMAT"
于 2019-10-11T16:33:24.793 回答
4

这是我不久前抓住的一个更好的功能:

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
}
于 2016-12-01T18:41:40.710 回答
1

这是对 bash 秒表的另一种看法,从这个线程中的其他答案中汲取了很多。此版本与其他版本的不同之处包括:

  • 这个版本使用 bash 算术而不是调用bc我发现(通过计时)来减少 cpu 时间。
  • 我已经解决了有人指出的 25 小时限制,方法是将 24 小时添加到每一天的小时部分。(所以现在我猜这是〜第 31 天的限制。)
  • 与接受答案中的版本不同,我将光标留在输出的右侧。这样,您只需按 Enter 即可轻松测量圈数(或更一般地标记重要事件时间),这会将计时器移动到下一行,使按键时的时间可见。
#!/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 秒时按回车键并在大约 9 分钟后按Ctrl-的示例输出:C

$ stopwatch
00:00:07
00:00:18
00:09:03^C
$

笔记:

  • 我使用+%-d:%-H:%-M:%-S日期的输出格式(这个破折号的意思是“请去掉任何前导零”),因为 printf 似乎将带有前导零的数字字符串解释为八进制并最终抱怨无效值。
  • 我摆脱了纳秒只是因为出于我的目的,我不需要超过 1 秒的精度。因此,我将sleep持续时间调整为更长以节省计算。
于 2019-12-30T00:12:33.340 回答
0

对于减法,您应该使用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 使用率以降低 CPU 使用率(在我的机器上没有它,它几乎是 15%,然后sleep它降低到 1%)。

于 2016-06-23T08:46:51.307 回答
0

基于rawaludin 的要点

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

于 2017-07-30T11:12:49.793 回答