Wie lösche ich eine Zeile mit Echo?


60

Ich weiß, dass ich die letzten drei Zeichen löschen konnte mit:

echo -ne '\b\b\b'

Aber wie kann ich eine ganze Zeile löschen? Ich meine, ich möchte nicht verwenden:

echo -ne '\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b'

... etc ... um eine lange Zeile zu löschen.


2
Für diejenigen, die ununterbrochen in dieselbe Zeile schreiben möchten: echo -ne "\033[2K" ; printf "\r"Jetzt ist die Zeile so gut wie neu, als wäre sie noch nie geschrieben worden.
Hallo Welt

2
Ich bin mir ziemlich sicher, dass Sie nur verwenden können echo -ne "\e[2K\r". Aber trotzdem ANSI-Escape-Sequenzen FTW.
Parthian Shot

Antworten:


57

Mit \boder können Sie \rden Cursor zurückbewegen und dann das gedruckte Zeichen mit einem neuen Zeichen überschreiben. Beachten Sie, dass die gedruckten Zeichen weder gelöscht \bnoch \rgelöscht werden. Es bewegt nur den Cursor zurück. \bBewegt den Cursor um ein Zeichen zurück und \rbewegt ihn an den Zeilenanfang.

Beispiel: beide

echo -e 'foooo\b\b\b\b\bbar'

und

echo -e 'foooo\rbar'

wird drucken:

baroo

Wenn Sie die Zeichen löschen möchten, müssen Sie die folgende Problemumgehung verwenden:

echo -e 'fooooo\r     \rbar'

Ausgabe:

bar  

Auszug aus man echo:

   If -e is in effect, the following sequences are recognized:

   \0NNN  the character whose ASCII code is NNN (octal)

   \\     backslash

   \a     alert (BEL)

   \b     backspace

   \c     produce no further output

   \f     form feed

   \n     new line

   \r     carriage return

   \t     horizontal tab

   \v     vertical tab

   NOTE: your shell may have its own version of echo, which usually super‐
   sedes the version described here.  Please refer to your  shell's  docu‐
   mentation for details about the options it supports.

4
Ja, aber es echo -e 'fooooooooo\rbarhallt nach barooooooo.
Mat

1
Ja, du hast recht. Beachten Sie, dass echo -e 'foooo\b\b\b\b\b\b\b\b\b\bbar'auch Echos baroo.
Lesmana

So süß, funktioniert auch einwandfrei printf.
Michael-O

4
Sehr ungenaue Antwort. Kevins ist wirklich besser
Mike Aski

87

Sie suchen nach terminalen Fluchten . Um insbesondere von der Cursorposition zum Zeilenanfang zu gelangen, gehen Sie wie folgt vor:

echo -e "\033[1K"

Oder alles in der Zeile, unabhängig von der Cursorposition:

echo -e "\033[2K"

Und Sie können alle möglichen anderen netten Tricks auch mit terminalen Fluchten ausführen.


6
Dies setzt ein VT100-kompatibles Terminal oder einen Emulator voraus (was heutzutage eine ziemlich sichere Annahme ist).
Keith Thompson

2
Wenn Sie etwas löschen möchten, das Sie gerade zurückgegeben haben, muss Ihr vorheriges Echo die
Markierung

1
Wenn Sie etwas anderes schreiben möchten, fügen Sie in der Zeile, die Sie löschen, ein -n-Flag in das Echo oben ein, oder Sie wechseln direkt nach dem Löschen zu einer neuen Zeile. Fügen Sie außerdem ein \ r an die oben stehende Zeichenfolge an, sonst wird Ihr neuer Inhalt nicht an den Anfang dieser Zeile verschoben.
DJJECK

-1 | -eAls echoArgument ist es nicht POSIX-konform. + Ich mag die Escape-Sequenzen nicht. Entweder lieber printfoder tput.
LinuxSecurityFreak

@Vlastimil warum würdest du das ablehnen? OP hat nicht nach einer Antwort gefragt, die Sie möchten. Vielleicht hätte er präzisierte , dass -eParameter für echonicht konform ist POSIX aber immer noch ...
Souki

35

Wenn Sie die Zeile löschen möchten, dann schlage ich vor, dass Sie eine Kombination aus den von den Personen erwähnten Zeilenumbrüchen und den Endungen verwenden.

# terminfo clr_eol
ceol=$(tput el)
echo -ne "xyzzyxyzzy\r${ceol}foobar"

Dies schreibt xyzzyxyzzy, kehrt dann zum Zeilenanfang zurück und sendet die Sequenz "Löschen bis Zeilenende" an das Terminal und schreibt dann foobar. Das -nMarkenecho fügt nach dem keine neue Zeile hinzu foobar.


4
Ich mag den zukunftssicheren Teil dieser speziellen Lösung - wenn man tput verwendet, funktioniert das möglicherweise auf jeder Art von Terminal.
Amos Shapira

2
Besser als printf '%s\r%s%s' xyzzyxyzzy "$ceol" foobarfür die Portabilität und zu vermeiden , den Inhalt mit $ceoldurchgehender \xExpansion.
Stéphane Chazelas

Beste Antwort, wenn auch nur, weil es mit beliebig langen Zeilen funktioniert. Vielen Dank!
Raphael

perfekt arbeiten. Aber wenn ich die Größe des Terminalbildschirms kleiner als die der Ausgabezeile ändere, wird es chaotisch.
K.Sopheak

11

Sie fragen ausdrücklich nach echo, aber diese Anfrage bringt Sie auf den Punkt. Hier ist ein Ansatz, der bashs eingebauten printfBefehl mit Klammererweiterung verwendet :

printf 'fooooooooo' # 10 characters
printf '\r'; printf ' %0.s' {0..9} # 10 expansions of the space character

1
perfekt! genau das, was ich brauchte
Omar S.

2
printf 'Status: gestartet'; Ruhezustand 2s; printf '\ r'; printf 'Status: aktualisiert'; Ruhezustand 2s; printf '\ r';
Omar S.

4

Hier ist ein Beispiel für die Verwendung der Optionen no newline -n und carriage return von echo \r.

Bash Terminallinie überschreiben

#!/bin/bash

CHECK_MARK="\033[0;32m\xE2\x9C\x94\033[0m"

echo -e "\n\e[4mDoing Things\e[0m"
echo -n "doing thing 1..."
sleep 1
echo -e "\\r${CHECK_MARK} thing 1 done"

Häkchen funktioniert auch bei RHEL6. Schön für rein ästhetische Bearbeitungen meiner Skripte
oneindelijk

1

Stattdessen echo -en "\r"könnten Sie den printf "\r"Befehl auch als nützlich empfinden. Auf diese Weise können Sie die Zeichenfolge formatieren. z.B:

for sec in {1..100}; do printf "\r %04d" ${sec}; sleep 0.1; done

Normalerweise mache ich das auch, wenn ich mit langsamer Dateianalyse arbeite, um den Dateinamen anzuzeigen, der gerade ausgeführt wird, ohne eine Liste zu erstellen


-1 | Vielleicht wolltest du absichtlich einen Einzeiler machen, aber das ist eigentlich nur zum Testen gut. Ich würde es mit neuen Zeilen richtig umschreiben.
LinuxSecurityFreak

0

Als Frage ist die ganze Zeile zu löschen

Ich habe den folgenden Befehl mit Kombination von echound sedzum Löschen von Zeilen verwendet

Nach der Ausführung des Befehls ist das Ergebnis leer, da die Zeile durch keines ersetzt wird

Befehl

echo  "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" | sed -r "s/.*//g"

-1

Hier ist ein Beispiel für einen Countdown-Timer:

i=10
while [ $i -gt 0 ]; 
do 
  printf "$i seconds remaining       " && printf '\r\033[1B'
  i=`expr $i - 1`
  sleep 1
  printf '\033[1A'
done

-1 | Vielleicht wolltest du absichtlich einen Einzeiler machen, aber das ist eigentlich nur zum Testen gut. Ich würde es mit neuen Zeilen richtig umschreiben.
LinuxSecurityFreak

Dann mach weiter und füge eine neue Antwort hinzu. Oder schlagen Sie eine Bearbeitung meiner Antwort vor.
Mikiemorales
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.