出力をリダイレクトしようとすると、cut
常に空のようです。リダイレクトしないと、出力は期待どおりに端末に表示されます。 OS X 10.10およびLinux 4.1.6でも同様です。
これは働きます:
root@karla:~# nc 10.0.2.56 30003
[...] lots of lines [...]
これは働きます:
root@karla:~# nc 10.0.2.56 30003 | cat
[...] lots of lines [...]
これは働きます:
root@karla:~# nc 10.0.2.56 30003 | cut -d, -f 15,16
[...] lots of lines [...]
これはない
root@karla:~# nc 10.0.2.56 30003 | cut -d, -f 15,16 | cat
[nothing]
これはまたする
root@karla:~# cat messung1 | cut -d, -f15,16 | cat
[...] lots of lines [...]
cat
これはafterに限定されませんcut
。grep
、tee
標準リダイレクトを使用して>
も機能しません。
何の問題がありましたか?
答え1
出力がないのではなく、塊として出力されます。
多くのプログラムと同様に、cut
その出力は、もはや端末でないときにバッファリングされます。つまり、バッファがいっぱいになった場合にのみデータを書き込みます。通常、YMMVは約4または8KiBです。
以下を比較して簡単に確認できます。
(echo foo; sleep 1; echo bar) | cut -c2-
そして:
(echo foo; sleep 1; echo bar) | cut -c2- | cat
最初のケースでは1秒後にcut
出力が出力oo\n
されar\n
、2番目の場合はoo\nar\n
1秒後に出力がブロックされます。つまり、入力の終わりを確認し、終了時に出力をフラッシュする場合です。
あなたの場合、stdinはnc
接続が閉じられたときにのみ入力の終わりを見ることができるので、書き込むデータが4KiB蓄積された後にのみ出力を開始します。
この問題を解決するには、いくつかの方法を使用できます。
GNUまたはFreeBSDシステムでは、
stdbuf
特定のコマンドのバッファリング動作を調整するユーティリティを使用できます(stdioバッファリング動作を事前設定するためにLD_PRELOADハッキングを使用するため、すべてのコマンドに対して機能するわけではありません)。... | stdbuf -oL cut -d, -f15,16 | cat
cut
標準出力でラインベースのバッファリングを実行するように指示します。GNU などの一部のコマンドには、
grep
バッファリングに影響を与えるオプションがあります。 (--line-buffered
GNUの場合grep
)。pseudo-tty ラッパーを使用して、コマンドの標準出力を端末に強制的に送信できます。しかし、ほとんどのこれらのソリューションにはいくつかの欠点と制限があります。
unbuffer
expect
たとえば、これらの問題を解決するためによく言及されるスクリプトには多くのバグがあります。うまく機能するのは、次のよう
socat
に使用するときです。... | socat -u 'exec:"cut -d, -f15,16",pty,raw' -
バッファリングされていない出力をサポートする高度なテキスト処理ツールでテキストユーティリティを置き換えることができます。
awk
たとえば、GNUにはfflush()
出力をフラッシュする機能があります。したがって、あなたは次のようcut -d, -f15,16
に書くことができます。awk -F, -vOFS=, '{print $15,$16;fflush()}'
awk
その機能がない場合は、その機能を代わりにfflush()
使用できますsystem("")
。これは通常、コマンドを実行するコマンドです。ここでは空のコマンドを実行しますが、実際にはawk
コマンドを実行する前にコマンドの標準出力をフラッシュするために使用します。または、次のものを使用できます
perl
。perl -F, -lane 'BEGIN{$,=",";$|=1} print @F[14..15]'