端末の形式が.txt文書の形式と異なります。

端末の形式が.txt文書の形式と異なります。

時間を追跡するスクリプトがあります。

コンソールに出力を印刷すると、次の結果が表示されます。

0 Days, 00:00:33

txtファイルとして保存すると、次のような結果が得られます。

^[[2K
  0 Days, 00:00:33

パスワード:

now=$(date +%s)
diff=$(($now - $begin))
mins=$(($diff / 60))
secs=$(($diff % 60))
hours=$(($diff / 3600))
days=$(($diff / 86400))

printf "\33[2K\r%3d Days, %02d:%02d:%02d" $days $hours $mins $secs
printf "\33[2K\r%3d Days, %02d:%02d:%02d" $days $hours $mins $secs >> test.txt

それはどこから来たのです^[[2Kか?私はこれがprintfのフォーマットに関連していると思います。

ここでprintfの内容を読んだ。http://wiki.bash-hackers.org/commands/buildin/printf。しかし、私は賢明ではありません…

答え1

printfコマンドにエスケープ制御シーケンスがありますprintf "\33[2K.....(例:\e[2K行をクリア)。これは端末の制御コマンドでなければならず、端末装置でのみ理解して実行できます。

端末内でスクリプトを対話的に実行すると、端末はシーケンスを正しく解釈します。コマンドの出力をファイルに保存すると、現在のシーケンスを解釈する内容がないため、シーケンスは文字通り処理されます。

今これを行う:

cat test.txt

出力を印刷する前に、端末がシーケンスを再度正しく解釈することがわかります。

答え2

線の連続性

printf "\33[2K\r%3d Days, %02d:%02d:%02d" $days $hours $mins $secs
printf "\33[2K\r%3d Days, %02d:%02d:%02d" $days $hours $mins $secs >> test.txt

印刷時間情報として定義されます。同じ行ターミナル。それ\33[2K全体(現在)行をクリア\rカーソルを行の先頭に移動します。その効果は、時間情報を変更して変更されたように見えるようにすることです。それラインの一部。

改行文字がないことがわかりました(\n)フォーマット。質問には改行文字が表示されます(明確にするために追加された可能性があります)。

答え3

次のように自分で書いた。

\33[2K

端末に応じて、これを何かを行うように指示するように理解してください。 「コンソール」に言及したので、次のリストが記載されているconsole_codes(4)マニュアルページを確認できます。

ECMA-48 CSIシーケンス

CSI (または ESC [)の後に最大一連のパラメータが続きます。国立公園サービス(16)はセミコロンで区切られた10進数です。空または存在しないパラメータはゼロとして扱われます。パラメータの順序の前に疑問符が続くことがあります。

...

K: EL - 行をクリア

デフォルト:カーソルから行末まで。
ESC [ 1 K:その行の先頭からカーソルまでの内容を削除します。
ESC [ 2 K:行全体を削除します。

(これは回想\033と同一性に役立ちますESC)。

したがって、エスケープシーケンスは、その端末の「完全行消去」コマンドです。

このコードを書く移植可能できれいな方法は次のとおりです。

clear_line=`tput cr; tput el`
printf "${clear_line}%3d Days, %02d:%02d:%02d" $days $hours $mins $secs

使用は、タスクをtputサポートしていない端末やel他のエスケープシーケンスを使用して、それをサポートする端末に書き込むときに理解できないゴミの代わりに適切な出力を得ることを意味します。


PS GNUを仮定すると、これらすべての算術はおそらく不要ですdate。 7日を超えないと、7日に短縮できます。

date -u -d "-$begin seconds +3days" '+${clear_line}%w days, %T'

それ以外の場合はまだ計算が必要です$daysが、次のように秒形式を指定できます%T

now=$(date +%s)
diff=$(($now - $begin))
days=$(($diff / 86400))
date -u -d "00:00 $diff seconds" '+${clear_line}$days days, %T'

関連情報