Stdinの各行の前に、生成にかかった時間の情報を付加するスクリプトが必要です。基本的に入力用:
foo
bar
baz
私はを頂きたい
0 foo
10 bar
5 baz
Fooの印刷とバーの印刷の間で10が10秒経過した場合、5の場合と同様に、バーを印刷してからbazを印刷するのに5秒かかりました。
タイムスタンプを表示するユーティリティts
があり、 https://github.com/Paypal/gnomon について知っていますが、JavaScriptを使用したくないと思います。
そのための標準ツールはありますか、それともawkを使用して処理を行う必要がありますか?
出力を生成するスクリプトがgenerate
と呼ばれると仮定しましょう。次に、各行を生成するのにかかる秒数を表示するには、次のようにします。
_$ generate | ( t0=$(date +%s); while read -r line; do t1=$(date +%s); echo " $((t1-t0)) $line"; t0=$t1; done )
2 foo
0 foo
5 foo
3 foo
_
同じコマンドが複数の行にまたがっていると、次のようになります。
_generate | ( t0=$(date +%s)
while read -r line
do
t1=$(date +%s)
echo " $((t1-t0)) $line"
t0=$t1
done
)
_
または、便宜上、次のコードを含むシェル関数を定義できます。
_timer() { t0=$(date +%s); while read -r line; do t1=$(date +%s); echo " $((t1-t0)) $line"; t0=$t1; done; }
_
この関数は次のように使用できます。
_$ generate | timer
0 foo
2 foo
4 foo
3 foo
_
t0=$(date +%s)
これにより、スクリプトの開始時の現在の時刻がEpoch以降の秒数でキャプチャされます。
_while read -r line; do
_
これにより、標準入力から読み取るループが開始されます
t1=$(date +%s)
これは、現在の回線がキャプチャされたEpoch以降の時間を秒単位でキャプチャします。
echo " $((t1-t0)) $line"
これにより、現在の行にかかった時間が秒単位で出力されます。
_t0=$t1
_
これにより、次の行の_t0
_が更新されます。
done
これは、while
ループの終了を示します。
_trickle () {
awk 'BEGIN { t = systime(); OFS="\t" }
{ print systime() - t, $0 }
{ t = systime() }'
}
_
この小さなシェル関数は、単にawk
スクリプトをラップします(GNU awk
と_mawk -Wi
_の両方と互換性がありますが、BSD awk
systime()
がないため、入力の各行に、出力の最後の行からの秒数が接頭辞として付けられます。最初の行には、ゼロが接頭辞として付けられます。
テスト:
_$ { echo hello; sleep 2; echo world } | trickle
0 hello
2 world
_
awk
スクリプトは、明らかにスタンドアロンでも実行できます。
_$ some_command | awk 'BEGIN{OFS="\t";t=systime()}{print systime()-t,$0;t=systime()}
_
例えば。
_$ { echo hello; sleep 2; echo world; } | awk 'BEGIN{OFS="\t";t=systime()}{print systime()-t,$0;t=systime()}'
0 hello
2 world
_
time
(注:シェル組み込みではなく、別のバイナリ)を使用して、whileループと組み合わせることができます。各コマンドの実行時間を取得するには:
while read -r line; do
/usr/bin/time -f "%e %C" $line 2>&1
done
出力例:
0.1 sleep 0.1
0.2 sleep 0.2
1.0 sleep 1
最初からの合計実行時間が必要な場合は、各ステップの実行時間を合計する必要があります。 %e
形式の精度は1/100秒であるため、 シェル整数演算 を直接使用することはできません(使用しているシェルによって異なります)。
total=0.0
while read -r line; do
t=$(/usr/bin/time -f "%e" $line 2>&1)
total=$(awk "BEGIN{print $total+$t}")
echo "$total $line"
done
出力例:
0.1 sleep 0.1
0.3 sleep 0.2
1.3 sleep 1
ええと、 moreutilsts
はそのための完璧なツールのようです:
$ seq 5 | pv -qL 1 | ts -s %s
2 1
4 2
6 3
8 4
10 5
またはより正確に:
$ seq 5 | pv -qL 1 | ts -s %.s
1.949228 1
3.933483 2
5.917923 3
7.902231 4
9.886618 5
または、zsh
またはksh93
を使用します($SECONDS
はデフォルトで整数ですが、typeset -F
; pdksh
およびbash
を使用して浮動にすることができます。 $SECONDS
もありますが、整数のみです):
$ typeset -F SECONDS=0; seq 5 | pv -qL 1 | while IFS= read -r line; do
printf '%.3f %s\n' "$SECONDS" "$line"; done
1.987 1
3.972 2
5.956 3
7.941 4
9.925 5
$ seq 5 | pv -qL 1 | ts -i %.s
1.947814 1
1.984442 2
1.984456 3
1.984151 4
1.984195 5
zsh
/ksh93
:
$ seq 5 | pv -qL 1 | while SECONDS=0; IFS= read -r line; do
printf '%.6f %s\n' "$SECONDS" "$line"; done
1.985298 1
1.984322 2
1.984212 3
1.984240 4
1.984441 5