系统:Linux 4.13.0-43-generic #48~16.04.1-Ubuntu BASH_VERSION='4.3.48(1)-发布'
命令:
while sleep 5
do
date +%T
done | awk -F: '{print $3}'
应打印“日期”输出的第三个字段(秒),每 5 秒一行。问题:仅当管道缓冲区已满时,awk 才从管道读取数据并处理其输入。即当生成超过 4K 的输入时。
当 awk 替换为 cat 时,按预期每 5 秒打印一行。
这个代码片段是从一个在其他系统上运行正常的shell脚本简化而来的,所以这个系统中一定有关于bash、awk及其配置的东西。
简而言之,有没有办法说服 awk 在从管道读取数据时表现得像 cat?
@Ed Morton:我确实尝试在每次打印后添加 fflush(),但它不起作用——这表明问题出在 awk 的输入上,而不是输出上。 我还尝试添加对 system("date") 的调用,这表明 awk 确实一次获取所有输入行,而不是在生成它们时立即获取。
对于那些提问的人:
$ awk -W version
mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan
compiled limits:
max NF 32767
sprintf buffer 2040
在尝试找出如何使 awk 打印其版本时,我发现它确实是 mawk,并且它具有以下标志:
-W interactive -- sets unbuffered writes to stdout and line buffered reads from stdin.
Records from stdin are lines regardless of the value of RS.
这似乎解决了问题!
感谢所有回复者。
stdbuf是一个通用的解决方案:
stdbuf - 运行命令,并修改其标准流的缓冲操作。
# buffered
while sleep 5; do date +%T; done | awk -F: '{print $0, strftime("%T")}' | ts %T
# unbuffered
while sleep 5; do date +%T; done | stdbuf -oL awk -F: '{print $0, strftime("%T")}' | ts %T
请安装
moreutils
以获取ts