내 스크립트는 비슷한 작업을 수행합니다.
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
깜박임을 방지하는 한 가지 방법은 화면을 지우고 다시 그리는 사이의 시간을 최소화하도록 화면을 지우기 전에 모든 출력을 얻는 것입니다. 이는 이중 버퍼링의 개념과 유사합니다.
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
현재 위치부터 화면 끝까지 인쇄합니다.
크기 조정 가능한 화면을 처리하려면 할당을 외부 루프 내부로 이동할 수 있습니다 ROWS
.COLS
#!/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
한 줄인지 여러 줄인지에 따라 다릅니다. 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이고 두 번째 반복 동안 $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