我有一个文件,其中连续附加数字:
1
2
3
4
我想计算它们的平均值,也是连续的,即:
1
1.5
2
2,5
我不想定期检查文件,我想以 tail -f 工作的方式进行检查 - 一旦添加一行,我就会执行平均计算。
是否可以?
更新型多巴胺问题已移至https://stackoverflow.com/questions/9400306/countinuous-processing-of-tail-f-output
答案1
是的。管道tail -f
连接到处理平均值的脚本。管道永远不会关闭,脚本可以立即处理收到的每一行...它会阻塞直到出现一行。
另外,大家应该记住,可以计算移动平均值而不必每次都添加所有值。我已经见过足够多的例子了,我觉得有必要提一下。
#generator.pl
$| = 1; #immediate flush
while (1) {
print int rand(100), "\n";
sleep 1;
}
#average.pl
$| = 1; #immediate output flush
my $average = 0;
my $count = 0;
while (<>) {
$average = ($average * $count + $_) / ($count + 1);
$count++;
print $average, "\n";
}
$ perl generator.pl > source &
[2] 15564
(reverse-i-search)`': ^C
$ tail -f source | perl average.pl
54
28
27.6666666666667
35
41
并且,只是为了开个玩笑:
$tail -f source | awk '{total+=$0; count+=1; print total/count}'
这也具有即时反馈。在我看来,您的问题是由正在写入 tail 正在读取的文件的应用程序缓冲引起的。
看http://www.pixelbeat.org/programming/stdio_buffering/了解相关信息。
答案2
这是一个使用 dc 的简单解决方案。
tail -f | dc -e '5k 0 d sc st [? lc 1 + sc lt + st lt lc / p c lax] sa lax'
我不确定 dc 是否支持尾递归,如果不支持,该程序将会泄漏内存。dc 的文档真的很糟糕。:)
怎么,你不喜欢脑力劳动?:)
这是一个 Ruby 中的简单解决方案。
tail -f | ruby -e 'sum=total=0.0; while line=gets; total += line.to_f; sum += 1; puts total/sum; end'