4

これは本当にシンプルなストップウォッチのように考えることができます。指定された日付からの経過時間を表示し、出力を1秒ごとに更新するbashスクリプトを一緒にハックしようとしています。

まず、スクリプト内でUNIXの日付を指定しますFri Apr 14 14:00:00 EDT 2011。これは、ストップウォッチが開始するときです。

これで、スクリプトを実行すると、次のように表示されます...

06d:10h:37m:01s

そして数秒後にあなたは見るでしょう...

06d:10h:37m:05s

経過する秒ごとに新しい行を印刷しようとはしていません。スクリプトには1行の出力しかなく、毎秒更新する必要があります。明らかに、スクリプトを終了していつでも再起動できますが、開始時刻がハードコーディングされているため、スクリプトは引き続き有効です。

何か案は?

4

3 に答える 3

5

長時間実行されるスクリプトでは、次のコードスニペットを使用します。タイマーは、メインプロセスがキーボード割り込みによって終了した場合に強制終了(トラップ)される関数(個別のプロセス)で実行されます。出力には、タイマーの開始から経過した時間が表示されます。

... working [hh:mm:ss]  00:07:58

スニペット:

#===  FUNCTION  ================================================================
#          NAME:  progressIndicatorTime
#   DESCRIPTION:  Display a progress indicator with seconds passed.
#    PARAMETERS:  [increment]   between 1 and 60 [sec], default is 2 [sec]
#===============================================================================
function progressIndicatorTime ()
{
  declare default=2                                       # default increment [sec]
  declare increment="${1:-$default}"                      # 1. parameter or default
  declare format='\b\b\b\b\b\b\b\b%02d:%02d:%02d'         # time format hh:mm:ss
  declare timepassed=0
  declare seconds minutes hours

  [[ ! "$increment" =~ ^([1-9]|[1-5][0-9]|60)$ ]] && increment=$default
  printf " ... working [hh:mm:ss]  00:00:00"
  while : ; do                                            # infinite loop 
    ((seconds=timepassed%60))
    ((minutes=timepassed/60))
    ((hours=minutes/60))
    ((minutes=minutes%60))
    printf "$format" $hours $minutes $seconds
    sleep $increment || break                             # sleep ...
    ((timepassed+=increment))
  done
}    # ----------  end of function progressIndicatorTime  ----------

progressIndicatorTime &                                   # run progress indicator
declare progressIndicatorPid=${!}                         # save process ID
trap  "kill $progressIndicatorPid" INT TERM               # trap keyboard interrupt

#
# run long command
#

kill -s SIGTERM $progressIndicatorPid                     # terminate progress indicator
于 2012-04-20T10:09:31.667 に答える
3

アートはいくつかの作品を使用することができますが、これを試してみてください:

#!/bin/bash

ref_date='Thu Apr 19 17:07:39 CDT 2012'
ref_sec=$(date -j -f '%a %b %d %T %Z %Y' "${ref_date}" +%s)
update_inc=1

tput clear
cat <<'EOF'


            [|]     [|]
         _-'''''''''''''-_
        /                 \
       |                   |
       |                   |
       |                   |
        \                 /
         '-_____________-'
EOF

while :
do
  ((sec=$(date +%s) - ${ref_sec}))
  ((day=sec/86400))
  ((sec-=day*86400))
  ((hour=sec/3600))
  ((sec-=hour*3600))
  ((min=sec/60))
  ((sec-=min*60))
  tput cup 6 14
  printf "%.2id:%.2ih:%.2im:%.2is\r" ${day} ${hour} ${min} ${sec}
  sleep ${update_inc}
done

exit 0

最初のデートコマンドの構文はOSX用であることに注意してください。

GNU日付には、date --date="${ref_date}" +%s

于 2012-04-19T23:36:52.737 に答える
1

Bash4またはksh93を使用している場合は、printf %()T構文を使用してstrftimeフォーマットを印刷できます。次の例は、必要な形式でのBash4印刷です。バッシュの精度は1秒に制限されています。ksh93はfloatをサポートしており、いくつかの変更が必要になります。

#!/usr/bin/env bash

# To supply a default date/time. To use now as the default, leave empty, or run with a null first arg.
deftime='Fri Apr 14 14:00:00 EDT 2011'

if (( ${BASH_VERSINFO[0]}${BASH_VERSINFO[1]} >= 42 )); then
    unixTime() {
        printf ${2+-v "$2"} '%(%s)T' -1
    }
else
    unixTime() {
        printf ${2+-v "$2"} "$(date '+%s')"
    }
fi

stopWatch() {
    local timestamp="$(date ${1:+'-d' "$1"} '+%s')" curtime day=$((60*60*24)) hour=$((60**2))
    # unixTime -1 timestamp

    while
        unixTime -1 curtime
        (( curtime -= timestamp ))
        printf '%02dd:%02dh:%02dm:%02ds\r' $(( curtime / day )) $(( (curtime / hour) % 24 )) $(( (curtime / 60) % 60 )) $(( curtime % 60 ))
        do sleep 1
    done
}

stopWatch "${1-deftime}"

$SECONDS変数にも興味があるかもしれません。残念ながら、人間が読める形式の日付を希望どおりに受け入れる便利な方法はありません。かなりの解析作業が必要になります。dateコマンド(特にGNU date)は、限られた範囲でそれを行うことができます。

于 2012-04-19T14:59:36.917 に答える