web-dev-qa-db-ja.com

bashを使用して端末の最後の行を削除および置換する方法は?

経過時間をbashで表示するプログレスバーを実装したいと思います。そのためには、画面に表示されている最後の行を消去する必要があります(「clear」コマンドはすべての画面を消去しますが、進行状況バーの行のみを消去し、新しい情報に置き換える必要があります)。

最終結果は次のようになります。

$ Elapsed time 5 seconds

次に、10秒後に(画面の同じ位置にある)この文を次のように置き換えます。

$ Elapsed time 15 seconds
84
Debugger

\ rでキャリッジリターンをエコーし​​ます

seq 1 1000000 | while read i; do echo -en "\r$i"; done

マンエコーから:

-n     do not output the trailing newline
-e     enable interpretation of backslash escapes

\r     carriage return
105
Ken

キャリッジリターン自体は、カーソルを行の先頭に移動するだけです。出力の各新しい行が前の行と少なくとも同じ長さであれば問題ありませんが、新しい行が短い場合、前の行は完全には上書きされません、例えば:

$ echo -e "abcdefghijklmnopqrstuvwxyz\r0123456789"
0123456789klmnopqrstuvwxyz

新しいテキストの行を実際にクリアするには、\033[K 後に \r

$ echo -e "abcdefghijklmnopqrstuvwxyz\r\033[K0123456789"
0123456789

http://en.wikipedia.org/wiki/ANSI_escape_code

172
Derek Veit

Derek Veitの答えは、行の長さが端末の幅を超えない限りうまく機能します。そうでない場合、次のコードはジャンク出力を防ぎます。

行が初めて書かれる前に、する

tput sc

現在のカーソル位置を保存します。行を印刷したいときはいつでも

tput rc
tput ed
echo "your stuff here"

最初に保存されたカーソル位置に戻り、次にカーソルから下に画面をクリアし、最後に出力を書き込みます。

17
Um.

\ 033メソッドはうまくいきませんでした。\rメソッドは機能しますが、実際には何も消去されず、カーソルを行の先頭に置くだけです。したがって、新しい文字列が古い文字列よりも短い場合、行の最後に残ったテキストを見ることができます。最後に、tputが最善の方法でした。カーソル以外の用途があり、多くのLinuxおよびBSDディストリビューションにプリインストールされているため、ほとんどのbashユーザーが利用できます。

#/bin/bash
tput sc # save cursor
printf "Something that I made up for this string"
sleep 1
tput rc;tput el # rc = restore cursor, el = erase to end of line
printf "Another message for testing"
sleep 1
tput rc;tput el
printf "Yet another one"
sleep 1
tput rc;tput el

プレイする小さなカウントダウンスクリプトを次に示します。

#!/bin/bash
timeout () {
    tput sc
    time=$1; while [ $time -ge 0 ]; do
        tput rc; tput el
        printf "$2" $time
        ((time--))
        sleep 1
    done
    tput rc; tput ed;
}

timeout 10 "Self-destructing in %s"
11
lee8oi

進行状況の出力が複数行の場合、またはスクリプトがすでに改行文字を出力している場合、次のような行をジャンプできます。

printf "\033[5A"

これにより、カーソルが5行上にジャンプします。その後、必要なものを上書きできます。

それでもうまくいかない場合は、printf "\e[5A" または echo -e "\033[5A"、これは同じ効果があります。

基本的に、 エスケープシーケンス を使用すると、画面内のほとんどすべてを制御できます。

5
Mr. Goferito

復帰文字を使用します。

echo -e "Foo\rBar" # Will print "Bar"
4
Mikael S

キャリッジリターン\r

printfを含む1行のコード

for i in {10..1}; do printf "Counting down: $i\r" && sleep 1; done

またはecho -ne

for i in {10..1}; do echo -ne "Counting down: $i\r" && sleep 1; done
1
Akif