我可以为tr禁用缓冲吗


10

tr似乎要缓冲其输入,以便该命令LongRunningCommand|tr \\n ,仅在LongRunningCommand积累了几千字节的输入后才开始产生输出。

有没有一种方法可以强制tr停止此缓冲,或者可以使用其他字符替换新行而不进行缓冲的任何其他命令?


PS我已经尝试了关闭管道中的缓冲但没有成功的前两个建议。


1
stdbuf对LongRunningCommand或对tr或对两者的申请都不同吗?
meuh 2015年

要像这样:stdbuf -o0 fping -aAq -r2 -g 10.30.0.1 10.30.0.255 2>/dev/null | stdbuf -i0 tr \\n ,
ndemou

fping -q说“不显示每个探针的结果,而只显示最终摘要”,那么也许最后只写了一个长篇幅?
2015年

没有fping命令本身可以正常工作。不过,非常感谢您的建议
ndemou 2015年

2
我认为缓冲问题实际上是在的输出tr。试试|stdbuf -i0 -o0 tr ...
meuh 2015年

Answers:


12

命令通常不缓冲其输入。他们会read()为较大的块执行a操作,但是当从管道中读取时,如果管道中没有那么多字节,read()系统调用将返回具有尽可能多的字符,并且如果可以的话,应用程序通常会使用该字符。

值得注意的例外是mawk它将一直保持read()到输入缓冲区已满。

应用程序确实会缓冲其输出(stdout)。通常的行为是,如果输出要发送到tty,则缓冲将是逐行的(也就是说,直到有完整的行要输出时才开始向stdout写入,或者对于完全长行),而对于其他所有类型的文件,缓冲都是按块进行的(也就是说,直到有一个完整的块要写入时才开始写入(类似于4KiB / 8KiB ...取决于软件和系统) ))。

因此,在您的情况下,LongRunningCommand可能会按块缓冲其输出(因为它的输出是管道而不是tty),并且tr可能会按行缓冲其输出,因为它的输出可能是终端。

但是,由于从输出中删除了每个换行符,它将永远不会输出一行,因此缓冲将按块进行。

所以在这里要为两禁用缓存LongRunningCommandtr。在GNU或FreeBSD系统上:

stdbuf -o0 LongRunningCommand | stdbuf -o0 tr '\n' ,

请注意,如果要用逗号将行连接起来,则最好使用paste -sd , -。这样,输出将以换行符终止(您可能仍需要禁用缓冲)。


@mikeserv。是的,它本身使用stdio缓冲并且不调用setvbuf / setbuffer ...,并且不是内置的shell。但是通常在GNU和FreeBSD系统上,所有这些条件都可以满足。
斯特凡Chazelas

哦。我只是几天前才得知自己的,当时我感到失望,因为我无法影响静态编译的I / O流sed。抱歉,如果这很烦人-但我没有意识到这是常识。我猜它使用LD_PRELOAD。
mikeserv

感谢您对斯特凡(Stéphane)的情况进行了详尽的解释。非常感谢
ndemou

5

要用替换换行符",",您可以运行

awk '{ printf "%s,", $0 }'

当输出到终端时,GNU awk(gawk)和Solaris nawk将在stdin上运行行缓冲,而没有stdout缓冲。如果awk是mawk在Ubuntu上发生的情况,则可以给它-W interactive提供获得相同缓冲行为的选项。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.