web-dev-qa-db-ja.com

パイプから読み取るときにawkが完全なバッファリングを行うのはなぜですか

Nmea文字列を送信するgpsデバイスに接続されたシリアルポートから読み取っています。

私のポイントを説明するための単純化された呼び出し:

  $ awk '{ print $0 }' /dev/ttyPSC9 
  GPGGA,073651.000,6310.1043,N,01436.1539,E,1,07,1.0,340.2,M,33.3,M,,0000*56
  $GPGSA,A,3,28,22,09,27,01,19,17,,,,,,2.3,1.0,2.0*39
  $GPRMC,073651.000,A,6310.1043,N,01436.1539,E,0.42,163.42,070312,,,A*67
  GPGGA,073652.000,6310.1043,N,01436.1540,E,1,07,1.0,339.2,M,33.3,M,,0000*55
  $GPGSA,A,3,28,22,09,27,01,19,17,,,,,,2.3,1.0,2.0*39

代わりにパイプから読み取ろうとすると、awkは入力をバッファーしてからstdoutに送信します。

$ cat /dev/ttyPSC9 | awk '{ print $0 }'
<long pause>
GPGGA,073651.000,6310.1043,N,01436.1539,E,1,07,1.0,340.2,M,33.3,M,,0000*56
$GPGSA,A,3,28,22,09,27,01,19,17,,,,,,2.3,1.0,2.0*39
$GPRMC,073651.000,A,6310.1043,N,01436.1539,E,0.42,163.42,070312,,,A*67
GPGGA,073652.000,6310.1043,N,01436.1540,E,1,07,1.0,339.2,M,33.3,M,,0000*55
$GPGSA,A,3,28,22,09,27,01,19,17,,,,,,2.3,1.0,2.0*39

バッファリングを回避するにはどうすればよいですか?

編集:カイルジョーンズは、猫が出力をバッファリングすることを提案しましたが、発生していないようです:

$ strace cat /dev/ttyPSC9 | awk '{ print $0 }'
write(1, "2,"..., 2)                    = 2
read(3, "E"..., 4096)                   = 1
write(1, "E"..., 1)                     = 1
read(3, ",0"..., 4096)                  = 2

私がそれについて考えるとき、私はプログラムが端末への書き込み時に行バッファリングを使用し、他のすべての場合には「通常のバッファリング」を使用すると考えました。では、なぜ猫はそれ以上バッファリングしないのですか?シリアルポートはEOFを通知していますか?では、なぜ猫は終わらないのですか?

23
Daniel Näslund

猫ではなくawkでバッファリングされている可能性があります。最初のケースでは、入力と出力がTTYであるため、awkはインタラクティブであると考えています(TTYが異なっていても、awkがチェックしていないと思います)。 2番目の例では、入力はパイプなので、非インタラクティブに実行されます。

Awkプログラムで明示的にフラッシュする必要があります。ただし、これは移植可能ではありません。

出力をフラッシュする方法の詳細と背景については、以下を参照してください。 http://www.gnu.org/software/gawk/manual/html_node/I_002fO-Functions.html

10
camh

私はそれが古い質問であることを知っていますが、ワンライナーはここに来る人々を検索するのを助けるかもしれません:

_cat /dev/ttyPSC9 | awk '{ print $0; system("")}'
_

system("")はトリックを行い、POSIXに準拠しています。非posixシステム:注意してください。

同じことを行うより具体的な関数fflush()が存在しますが、古いバージョンのawkでは使用できません。

system("")の使用に関する the docs の重要な情報:

gawkはこのsystem()関数の使用を特殊なケースとして扱い、空のコマンドでシェル(または他のコマンドインタープリター)を実行しないように十分にスマートです。したがって、gawkでは、このイディオムは便利なだけでなく、効率的でもあります。

39
Shrein