Verhindern Sie, dass Text / Bildschirm beim Löschen blinkt


11

Mein Skript macht so etwas wie:

while :;
   clear

   do_a_lot_of_output_here

   sleep 1
done

Gibt es Optionen, um zu verhindern, dass der Bildschirm beim Löschen und Ausgeben blinkt? Ich möchte es wie im watchBefehl machen (aber es ist in geschrieben C). Irgendwelche Ratschläge?

clear | hexdump -C

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

PS. Ich benutze bashnur.


Können Sie die Ausgabe von Ihrem hinzufügen clear | hexdump -C?
ott--

Ich habe die Frage erweitert.
Ravnur

Ich fand eine andere Lösung auf stackoverflow.com/questions/5367068/... - tutecho -en "\ec" blinkt auch?
ott--

Ich habe diesen auch gefunden. Beide Varianten von Antwortblitz auch.
Ravnur

Ich hatte Erfolg mit diesem Tool: excess.org/article/2009/07/watch1-bash-unicode
Raine

Antworten:


8

Das Blinken tritt auf, weil das Skript den gesamten Bildschirm löscht. Wenn der vorhandene Text übermalt und nur bei Bedarf gelöscht wird, tritt kein Flackern auf.

Hier ist ein Beispiel:

#!/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

Es macht das:

  • druckt die Ausgabe des angegebenen Befehls, der auf den Bildschirm passt (kein Umbrechen oder Scrollen)
  • schreibt über vorhandene Zeilen und löscht den Teil jeder Zeile, der nicht überschrieben wird
  • Verwendet die edFunktion Ihres Terminals, um vom aktuellen Speicherort bis zum Ende des Bildschirms zu drucken.

Wenn Sie einen Bildschirm mit veränderbarer Größe bearbeiten möchten, können Sie die Zuweisungen in ROWSund COLSinnerhalb der äußeren Schleife verschieben, z.

#!/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

weil tputfragt nach der aktuellen Bildschirmgröße vom System.

Weiterführende Literatur:


1
Für diejenigen, die Embedded in einem kleinen eigenständigen Skript mit einigen Funktionen verwenden #!/bin/bashund verwenden möchten watchit, können Sie dies tun export -f function_name; watchit function_name.
Aggregat1166877

Dies funktionierte perfekt für mich, außer dass ich oben auf dem Bildschirm auf lustige Probleme stieß, bei denen sich die Dinge verschoben und für längere Textblöcke unangenehm wurden (alles, was durch verkürzt wurde head). Das Problem scheint ein Fehler zu sein (zumindest in meinem Setup - SSH-Sitzung in geteilten Fenstern, iTerm2), wenn die Anzahl der Zeilen berechnet wird. ROWS=`expr $(tput lines) - 1`hat dies perfekt angesprochen.
Ohruunuruus

Das ist wunderbar, vielen Dank @ thomas-dickey.
Mbarkhau

9

Eine Möglichkeit, ein Blinken zu verhindern, besteht darin, die gesamte Ausgabe vor dem Löschen des Bildschirms abzurufen, sodass zwischen dem Löschen und dem erneuten Zeichnen eine minimale Zeitspanne liegt. Dies ähnelt dem Konzept der doppelten Pufferung:

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

Dadurch wird das Flimmern nicht vollständig beseitigt, aber meiner Erfahrung nach tritt es deutlich seltener auf.


Doppelte Pufferung, wie in jeder anderen Situation, sichert den Tag :-)
Ikke

Lief wie am Schnürchen. Kein Flackern :)
Lars Juel Jensen

1
Das verbleibende Flackern kann beseitigt werden, indem das clearin den Puffer aufgenommen wird, d output=$(clear; do_a_lot_of_output_here). H.
kdb

@kdb Netter Vorschlag! Dies eliminiert das Flackern für mich fast vollständig und ist viel einfacher als die akzeptierte Antwort.
Michael Mior

Das funktioniert wie ein Zauber! Zuerst habe ich die doppelten Anführungszeichen im 'echo "$ output"' verpasst, und dann sind die Zeilen durcheinander. (Alle Leerzeichen werden als einzelne Leerzeichen betrachtet.)
Popup

5

Das Blinken ist ein unvermeidbares Ergebnis des Löschens des Bildschirms jedes Mal um die Schleife herum. Sie können den Cursor an den oberen Bildschirmrand bewegen und stattdessen Teile Ihrer alten Ausgabe überschreiben.

# 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

Dieses Skript hinterlässt Artefakte, wenn Ihre Ausgabe kleiner wird. Es ist auch nicht sehr wahrscheinlich, tragbar zu sein. Ich habe es nur mit urxvt, xterm und st getestet.


In diesem Fall springt der Cursor von einer zufälligen Position (und natürlich von Artefakten) zum Ende der Ausgabe. Auch ich habe es tput clearmit den gleichen Ergebnissen versucht (blinkend)
Ravnur

Ich habe dem Skript einige Zeilen hinzugefügt, um den Cursor auszublenden.

Kein Cursor - kein Springen. Aber über Artefakte? Die Ausgabe hat eine zufällige Anzahl von Zeilen. Muss ich alle Skripte mit Leerzeichen füllen, bevor ich eine neue Ausgabe starte? Aber trotzdem, danke für deine Zeit und deine Bemühungen: +1 von mir dafür, aber es löst mein Problem nicht
Ravnur

Ich habe nur einen Weg gefunden, um alle Artefakte loszuwerden : tput ed. Aber es verursacht ein Blinken
Ravnur

Welchen Terminalemulator verwenden Sie? Mit tput edrechts vor der do_a_lot...Linie, ich sehe in urxvt aber nicht xterm oder st zu blinken.

1

Als Erweiterung von Cristians Antwort habe ich die folgende Bash-Funktion erstellt, die funktioniert, wenn das Konsolenfenster kleiner als die Ausgabe des Befehls ist:

function watcher()
{
    lines=$(tput lines)
    while true; do
        output="$($@ | head -n $lines)"
        clear
        echo -e "$output"
        sleep 2
    done
}

Auf diese Weise können Sie einen beliebigen Befehl an den Beobachter übergeben. Wenn Sie git verwenden, verwenden Sie git config --global color.status alwaysund dann:

watcher git status

Zeigt eine ständig aktualisierte Ausgabe des Git-Status an.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.