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