削除時のテキスト/画面のちらつきを防ぐ

削除時のテキスト/画面のちらつきを防ぐ

私のスクリプトは同様のことをします。

while :;
   clear

   do_a_lot_of_output_here

   sleep 1
done

クリアや出力時に画面がちらつく現象を防止するオプションはありますか?私はwatch命令のようにこれをしたいと思います(しかしそれはに書かれていますC)。どんな提案がありますか?

clear | hexdump -C

00000000  1b 5b 48 1b 5b 32 4a                              |.[H.[2J|
00000007

PS。私はbash

答え1

ちらつきを防ぐ1つの方法は、画面を消去して再描画するまでの時間を最小限に抑えるために、画面を消去する前にすべての出力を取得することです。これは二重バッファリングの概念に似ています。

while :; do
   output=$(do_a_lot_of_output_here)
   clear
   echo "$output"
   sleep 1
done

これにより、ちらつきは完全に削除されませんが、私の経験では、ちらつきの発生頻度は大幅に減少します。

答え2

点滅は、スクリプトが画面全体を消去するために発生します。既存のテキストを上書きして必要なときだけ消去すると、ちらつきは発生しません。

例は次のとおりです。

#!/bin/sh
watchit() {
    HOME=$(tput cup 0 0)
    ED=$(tput ed)
    EL=$(tput el)
    ROWS=$(tput lines)
    COLS=$(tput cols)
    printf '%s%s' "$HOME" "$ED"
    while true
    do
        CMD="$@"
        ${SHELL:=sh} -c "$CMD" | head -n $ROWS | while IFS= read LINE; do
            printf '%-*.*s%s\n' $COLS $COLS "$LINE" "$EL"
        done
        printf '%s%s' "$ED" "$HOME"
        sleep 1
    done
}

watchit top -b -n 1

これは次のことを行います。

  • 与えられたコマンドの出力を画面に合わせて印刷します(改行やスクロールなし)。
  • 既存の行を上書きし、各行で見つからない部分を消去します。
  • 端末の機能を使用して、現在ed位置から画面の終わりまで印刷します。

サイズ変更可能な画面を処理するには、割り当てを外部ループ内に移動できますROWSCOLS

#!/bin/sh
watchit() {
    HOME=$(tput cup 0 0)
    ED=$(tput ed)
    EL=$(tput el)
    printf '%s%s' "$HOME" "$ED"
    while true
    do
        ROWS=$(tput lines)
        COLS=$(tput cols)
        CMD="$@"
        ${SHELL:=sh} -c "$CMD" | head -n $ROWS | while IFS= read LINE; do
            printf '%-*.*s%s\n' $COLS $COLS "$LINE" "$EL"
        done
        printf '%s%s' "$ED" "$HOME"
        sleep 1
    done
}

watchit top -b -n 1

なぜなら、tputシステムは現在の画面サイズを取得する必要があるからです。

追加資料:

答え3

点滅は、画面が循環するたびに画面が消去されるのを避けられない結果です。カーソルを画面上部に移動し、前の出力の一部を上書きできます。

# You may want to do this if your code is in a script.
unhide_cursor() {
    printf '\e[?25h'
}
trap unhide_cursor EXIT

# Hide the cursor (there is probably a much better way to do this)
printf '\e[?25l'
clear 
while true ; do
    # Move the cursor to the top of the screen but don't clear the screen
    printf '\033[;H' 
    do_a_lot_of_output_here
    sleep 1
done

出力が縮小されると、このスクリプトは成果物を残します。また携帯性が低下する場合もあります。私はurxvt、xterm、stでのみテストしました。

答え4

1行か複数行かによって異なります。 tputも悪い選択ではありませんが、escコードを使用する方が良いです...

while true
do
    printf "^[[H^[[0K$do_a_lot_of_output"
    sleep 0.01
done

^[[Hカーソルを0,0または左上に移動します。 ^[[0K は現在のカーソル位置から行末までの内容を削除します。

^[[0K現在のカーソル位置から行末まで行を消去し、次の文字列が前の文字列より短くなると、残りのデータが表示されないため、これをお勧めします。

たとえば、最初の反復中に$ do_a_lot_of_output = 20、2回目の反復中に$ do_a_lot_of_output = 5の場合、出力は50になります。 ^[[0Kが必要な範囲のみを出力するので、含めないと、20個のうち2個が新しい5で上書きされますが、0はまだ間違った50を提供します。

私の考えでは^ [[Kも書くことができると思います。

ctrl + vを押してescコードシーケンスを開始し、ESCを押して^ [を生成し、この場合は別の[ +コードHまたはKを追加します。

あなたはそれらを合わせて^[[Hまたは^[[Kを得る。

Ansiエスケープコードリスト: https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797

関連情報