キャリッジリターンを使用したスパム端末の出力リダイレクト

キャリッジリターンを使用したスパム端末の出力リダイレクト

毎秒数百行程度の非常に詳細な出力を生成するコマンドがあります。ただし、このコマンドは\r進行状況バーと同じ方法で前の出力行を上書きするために使用されます。時々、現在の出力線を「焼く」端子に改行文字を書き込みます。

この出力をファイルにリダイレクトすると、数百メガバイトの出力が生成されます。キャリッジリターンが発生すると、各行は「上書きされる」代わりにファイルに書き込まれます。

私はこれが期待される動作であることを知っており、この問題を解決する1つの方法は、プログラムをよりスマートにし、この対話状態を印刷する代わりにファイルにリダイレクトされることを認識することです。ただし、このプログラムを変更することはできません。

最終出力ファイルの内容が端末で対話的に実行されたときに表示されるものと同じになるように、この出力をパイプ/フィルタリングする方法はありますか?

私は試した:

spammy_cr_command | uniq

...出力はないものと同じです。uniq

そして:

spammy_cr_command | sed '/\r/d'

...これは改行文字を含む「焼き」行も削除します。

答え1

cmd | sed -e 's/.*\r//' > file

これにより、各行のキャリッジリターンの後のすべてのテキストが何も変わらず、最後のキャリッジリターンの後の行部分のみが残ります。これはない〜しなければならない端末に残っているのと同じですが、ほとんどの場合は近似です。


特に、1 行が次の行より長い場合は処理されません。このプログラムは間違った結果を提供します。

printf 'abcdefg\rxyz\n'
printf '123456789\r\nxyz\n'

なぜなら明らかに残るのは

xyzdefg
123456789
xyz

また、sed削除されていないすべての文字をスキップします。

xyz

xyz

プログラムがこのように動作することを確認できます。進行状況バーなどでカーソルが左端に固定されて、目的の結果が得られないことがよくあります。

答え2

col非常に生のTTY-37出力の場合、このコマンドはM. Homerの回答に記載されている問題なしに問題を解決します。 (これはsed単純なTTY-37ではなく、端末エスケープと制御シーケンスを含む出力を持つ操作のためのツールではありませんが、Stack Exchangeではcolsedそれほぼ8年が経ちました。 )

%
printf 'abcdefg\rxyz\n'
printf '123456789\r\nxyz\n'
)|列b
xyzの定義
123456789
XYZ
%

答え3

GNU awkを使用すると、オーバーライドの動作に近い操作を実行できます。

BEGIN { 
  RS = "[\r\n]"                   # split records on either CR or LF
  a = ""                          # variable to save the text for overwriting
} 
{
  a = $0 substr(a, 1 + length)    # save current line, add trailing part of saved text
} 
RT ~ /\n/ {                       # LF, time to print and reset
  print a;
  a = ""
}

Michael Homerの例では、次のようになります。

~ awk 'BEGIN { RS="[\r\n]" } {a = $0 substr(a, 1 + length)} RT ~ /\n/ {print a; a=""}' foo
xyzdefg
123456789
xyz

この変数にはGNU awkが必要で、そのレコードの正規表現にRT一致するレコード区切り文字のテキストが含まれています。RS

関連情報