改行文字を含む出力を端末にリダイレクトする

改行文字を含む出力を端末にリダイレクトする

1 秒あたり数百行という非常に詳細な出力を作成するコマンドがあります。ただし、このコマンドは、\rプログレス バーに似た方法で、出力の前行を上書きします。ときどき、ターミナルに改行が書き込まれ、現在の出力行が「焼き付けられる」ことがあります。

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

これは想定された動作であり、これを解決する 1 つの方法は、プログラムをよりスマートにして、ファイルにリダイレクトされていることを認識し、この対話型ステータスを印刷しないようにすることだと理解しています。ただし、このプログラムを変更することはできません。

この出力をパイプ/フィルター処理して、最終出力ファイルに表示される内容が、ターミナルで対話的に実行した場合に表示される内容と同じになるようにする方法はありますか?

私はもう試した:

spammy_cr_command | uniq

... 出力は、なしの場合と同じになりますuniq

そしてまた:

spammy_cr_command | sed '/\r/d'

...これにより、改行文字を含む「ベイクされた」行も削除されます。

答え1

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

これは、各行の最後の改行文字の後のテキストをすべて置き換え、最後の改行文字の後の行の部分だけを残します。これは必然的にただし、これは端末に残されるものと同じですが、ほとんどの場合、近似値になります。


特に、行が後続の行よりも長い場合は処理されません。このプログラムは誤った結果を返します。

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

目に見えて残るのは

xyzdefg
123456789
xyz

しかし、sed消去されていない文字もすべてスキップし、

xyz

xyz

プログラムがそのように動作するかどうかを判断できます。進行状況バーなどでカーソルが左端に置かれることは珍しくありませんが、その場合、期待した結果が得られない可能性があります。

答え2

非常に原始的なTTY-37出力の場合、このcolコマンドはM. Homerの回答で言及されている問題なしにこれを解決しますsed。(単純なTTY-37出力ではなく、端末のエスケープシーケンスと制御シーケンスを含む出力の場合、どちらもこのツールには適してcolいませんsed。ただし、Stack ExchangeにはQ&Aがあります。それすでに8年近くになります。

%
printf 'abcdefg\rxyz\n'
printf '123456789\r\nxyz\n'
) | 列 -b
xyzdefg
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

関連情報