libc の buffer と perl の buffer は違うんだよという話を聞いたのでちょい調べてみた。 libc の buffer は grep を pipe で複数つなぐとなかなか表示されないやつ
$ while : ; do echo hoge; sleep 1; done | grep hoge
↑これはすぐに hoge が表示されますが
$ while : ; do echo hoge; sleep 1; done | grep hoge | grep hoge
↑こっちはずーっと待ってないと出力されません。出力先が端末でない場合、fwrite とかは buffering されるんですね。すぐに出力したい場合は次のように
$ while : ; do echo hoge; sleep 1; done | grep --line-buffered hoge | grep hoge
“–line-buffered” オプションをつけることで、毎行 fflush() が実行されてすぐさま出力されます。もうひとつ
$ while : ; do echo hoge; sleep 1; done | stdbuf -o0 grep hoge | grep hoge
と、stdbuf で LD_PRELOAD を使って buffer をコントロールするという方法もあるようです。(How to fix stdio buffering) で、Perl もこんな仕組みで buffering されてるんだろうと思ってたら違うんですね。 7.12. Flushing Output
$ perl -e 'while (1) { print "hoge\n"; sleep 1; }' | grep hoge
$ stdbuf -o0 perl -e 'while (1) { print "hoge\n"; sleep 1; }' | grep hoge
このどちらもすぐには出力されません。 次のようにするしかないようです。(IO::Handle 使っても良い)
$ perl -e '$|=1; while (1) { print "hoge\n"; sleep 1; }' | grep hoge
なるほどねぇ。
awk には fflush() っていう関数があって、sed には –unbuffered というオプションがあるらしい。