linux 通过管道传输到awk的Bash命令有时会被缓冲

vshtjzan  于 12个月前  发布在  Linux
关注(0)|答案(2)|浏览(136)

系统:Linux 4.13.0-43-generic #48~16.04.1-Ubuntu BASH_VERSION ='4.3.48(1)-release'
命令:

while sleep 5
do
  date +%T
done | awk -F: '{print $3}'

字符串
应该打印“date”输出的第三个字段(秒),每5秒打印一行。问题:awk从管道中读取,并处理其输入,只有当管道的缓冲区已满时。
awk 替换为 cat 时,每5秒打印一行。
这个代码片段是从一个shell脚本简化而来的,这个shell脚本在其他系统上运行得很好,所以这个系统中一定有关于bash,awk和它们的配置的东西。
简而言之,有没有一种方法可以让 awk 在阅读管道时表现得像 cat 一样?
@艾德莫顿:我确实尝试在每次打印后添加 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

e0bqpujr

e0bqpujr1#

在尝试找出如何使 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.

字符串
这似乎解决了问题!
感谢所有replier。

e5njpo68

e5njpo682#

stdbuf是一个通用的解决方案:
stdbuf -运行COMMAND,并修改其标准流的缓冲操作。

# 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

相关问题