清除时防止文本/屏幕闪烁

rav*_*nur 14 bash

我的脚本执行如下操作:

while :;
   clear

   do_a_lot_of_output_here

   sleep 1
done
Run Code Online (Sandbox Code Playgroud)

当我清除和输出时,是否有任何选项可以防止屏幕闪烁?我想像在watch命令中那样做(但它是用 写的C)。有什么建议吗?

clear | hexdump -C

00000000  1b 5b 48 1b 5b 32 4a                              |.[H.[2J|
00000007
Run Code Online (Sandbox Code Playgroud)

附注。我bash只用。

小智 12

帮助防止闪烁的一种方法是在清除屏幕之前获取所有输出,以便在清除和重绘之间有最短的时间。这类似于双缓冲的概念:

while :; do
   output=$(do_a_lot_of_output_here)
   clear
   echo "$output"
   sleep 1
done
Run Code Online (Sandbox Code Playgroud)

这并不能完全消除闪烁,但根据我的经验,它发生的频率要低得多。

  • 剩余的闪烁可以通过将“clear”包含到缓冲区中来消除,即“output=$(clear; do_a_lot_of_output_here)”。 (2认同)

Tho*_*key 8

发生闪烁是因为脚本清除了整个屏幕。如果它覆盖现有文本并仅在必要时清除,则不会有闪烁。

下面是一个例子:

#!/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
Run Code Online (Sandbox Code Playgroud)

它这样做:

  • 打印适合屏幕的给定命令的输出(无换行或滚动)
  • 覆盖现有行,清除每行中未被覆盖的部分
  • 使用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
Run Code Online (Sandbox Code Playgroud)

因为tput从系统询问当前的屏幕大小。

进一步阅读:


小智 6

闪烁是每次循环清屏时不可避免的结果。您可以将光标移动到屏幕顶部并覆盖旧输出的部分内容。

# 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
Run Code Online (Sandbox Code Playgroud)

如果您的输出缩小,此脚本将留下工件。它也不太可能是便携式的。我只用 urxvt、xterm 和 st 测试过它。