我想要一个脚本,它将在 stdin 的每一行前面加上生成它需要多长时间的信息。基本上用于输入:
foo
bar
baz
Run Code Online (Sandbox Code Playgroud)
我想拥有
0 foo
10 bar
5 baz
Run Code Online (Sandbox Code Playgroud)
其中 10 是打印 foo 和打印 bar 之间经过的 10 秒,与 5 类似,打印 bar 后需要 5 秒才能打印 baz。
我知道有一个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
Run Code Online (Sandbox Code Playgroud)
分布在多行中的相同命令如下所示:
generate | ( t0=$(date +%s)
while read -r line
do
t1=$(date +%s)
echo " $((t1-t0)) $line"
t0=$t1
done
)
Run Code Online (Sandbox Code Playgroud)
或者,为了方便起见,我们可以定义一个包含以下代码的 shell 函数:
timer() { t0=$(date +%s); while read -r line; do t1=$(date +%s); echo " $((t1-t0)) $line"; t0=$t1; done; }
Run Code Online (Sandbox Code Playgroud)
我们可以这样使用这个函数:
$ generate | timer
0 foo
2 foo
4 foo
3 foo
Run Code Online (Sandbox Code Playgroud)
t0=$(date +%s)
这会以自纪元以来的秒数捕获脚本开始时的当前时间。
while read -r line; do
这将启动一个从标准输入读取的循环
t1=$(date +%s)
这将捕获当前行被捕获的时间(以秒为单位)。
echo " $((t1-t0)) $line"
这会打印出当前行花费的时间(以秒为单位)。
t0=$t1
这将更新t0下一行。
done
这标志着while循环的结束。
trickle () {
awk 'BEGIN { t = systime(); OFS="\t" }
{ print systime() - t, $0 }
{ t = systime() }'
}
Run Code Online (Sandbox Code Playgroud)
这个小小的 shell 函数简单地包装了一个awk脚本(与 GNUawk和兼容mawk -Wi,但与 BSD兼容,awk因为它缺少systime())。它将输出每行输入,前缀为自最后一行输出以来的整秒数。第一行将以零为前缀。
测试:
$ { echo hello; sleep 2; echo world } | trickle
0 hello
2 world
Run Code Online (Sandbox Code Playgroud)
该awk脚本显然也可以独立运行:
$ some_command | awk 'BEGIN{OFS="\t";t=systime()}{print systime()-t,$0;t=systime()}
Run Code Online (Sandbox Code Playgroud)
例如
$ { echo hello; sleep 2; echo world; } | awk 'BEGIN{OFS="\t";t=systime()}{print systime()-t,$0;t=systime()}'
0 hello
2 world
Run Code Online (Sandbox Code Playgroud)