Frage Wie lösche und ersetze die letzte Zeile im Terminal mit bash?


Ich möchte einen Fortschrittsbalken implementieren, der die verstrichenen Sekunden in bash anzeigt. Dazu muss ich die letzte Zeile auf dem Bildschirm löschen (Befehl "Löschen" löscht den gesamten Bildschirm, aber ich muss nur die Zeile des Fortschrittsbalkens löschen und durch die neue Information ersetzen).

Das Endergebnis sollte wie folgt aussehen:

$ Elapsed time 5 seconds

Dann nach 10 Sekunden möchte ich diesen Satz ersetzen (an der gleichen Stelle auf dem Bildschirm) durch:

$ Elapsed time 15 seconds

75
2018-03-05 16:06


Ursprung


Antworten:


echo einen Wagenrücklauf mit \ r

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

von Mann Echo:

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

\r     carriage return

97
2018-03-05 16:08



Der Wagenrücklauf bewegt den Cursor nur zum Anfang der Zeile. Das ist in Ordnung, wenn jede neue Zeile der Ausgabe mindestens so lang wie die vorherige ist, aber wenn die neue Zeile kürzer ist, wird die vorherige Zeile nicht vollständig überschrieben, z.

$ echo -e "abcdefghijklmnopqrstuvwxyz\r0123456789"
0123456789klmnopqrstuvwxyz

Um die Zeile für den neuen Text tatsächlich zu löschen, können Sie hinzufügen \033[K nach dem \r:

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

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


155
2017-07-21 10:06



Derek Veits Antwort funktioniert gut, solange die Zeilenlänge die Terminalbreite nicht überschreitet. Wenn dies nicht der Fall ist, verhindert der folgende Code die Junk-Ausgabe:

bevor die Zeile zum ersten Mal geschrieben wird, mach es

tput sc

welches die aktuelle Cursorposition speichert. Jetzt, wann immer Sie Ihre Linie drucken möchten, verwenden Sie

tput rc
tput ed
echo "your stuff here"

um zuerst zur gespeicherten Cursorposition zurückzukehren, dann den Bildschirm vom Cursor nach unten zu löschen und schließlich die Ausgabe zu schreiben.


16
2017-09-20 12:04



Die Methode \ 033 hat bei mir nicht funktioniert. Die Methode funktioniert, aber es löscht nichts, sondern setzt den Cursor an den Anfang der Zeile. Wenn also die neue Zeichenfolge kürzer als die alte ist, können Sie den übrig gebliebenen Text am Ende der Zeile sehen. Am Ende war tput der beste Weg zu gehen. Es hat andere Anwendungen neben dem Cursor-Zeug und es kommt vorinstalliert in vielen Linux & BSD-Distributionen, so dass es für die meisten Bash-Benutzer verfügbar sein sollte.

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

Hier ist ein kleines Countdown-Skript zum Spielen:

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

10
2018-01-14 20:45



Verwenden Sie das Wagenrücklaufzeichen:

echo -e "Foo\rBar" # Will print "Bar"

4
2018-03-05 16:09



Wenn die Fortschrittsausgabe mehrzeilig ist oder das Skript bereits das neue Zeilenzeichen gedruckt hat, können Sie Zeilen mit etwas nach oben springen:

printf "\033[5A"

Dadurch springt der Cursor 5 Zeilen nach oben. Dann können Sie überschreiben, was Sie brauchen.

Wenn das nicht funktionieren würde, könntest du es versuchen printf "\e[5A" oder echo -e "\033[5A", die den gleichen Effekt haben sollten.

Grundsätzlich mit Escape-Sequenzen Sie können fast alles auf dem Bildschirm steuern.


2
2018-05-19 22:16



Der einfachste Weg ist die Verwendung der \r Charakter denke ich.

Der Nachteil ist, dass Sie keine vollständigen Zeilen haben können, da nur die aktuelle Zeile gelöscht wird.

Einfaches Beispiel:

time=5
echo -n "Elapsed $time seconds"
sleep 10
time=15
echo -n "Elapsed $time seconds"

echo "\nDone"

-1
2018-03-05 16:13