Jak usunąć linię za pomocą echa?


60

Wiem, że mogłem usunąć ostatnie trzy znaki za pomocą:

echo -ne '\b\b\b'

Ale jak mogę usunąć pełną linię? Mam na myśli, że nie chcę używać:

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'

... itd. ... aby usunąć długą linię.


2
Dla tych, którzy chcieliby ciągle pisać w tej samej linii: echo -ne "\033[2K" ; printf "\r"teraz linia jest jak nowa, jakby nigdy wcześniej nie była napisana.
Hello World,

2
Jestem pewien, że możesz po prostu użyć echo -ne "\e[2K\r". Niemniej jednak sekwencje specjalne ANSI FTW.
Parthian Shot

Odpowiedzi:


57

Możesz użyć \blub, \raby przesunąć kursor do tyłu, a następnie zastąpić wydrukowany znak nowym znakiem. Pamiętaj, że ani \bnie \rusuwa drukowanych znaków. Po prostu przesuwa kursor do tyłu. \bprzesuwa kursor o jeden znak wstecz i \rprzesuwa kursor na początek linii.

Przykład: oba

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

i

echo -e 'foooo\rbar'

wydrukuje:

baroo

Jeśli chcesz usunąć znaki, musisz zastosować następujące obejście:

echo -e 'fooooo\r     \rbar'

wynik:

bar  

Fragment 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
Tak, ale echo -e 'fooooooooo\rbarecho barooooooo.
Mat.

1
Tak masz rację. Zauważ, że echo -e 'foooo\b\b\b\b\b\b\b\b\b\bbar'także echo baroo.
lesmana,

Tak słodki, działa nawet bezbłędnie printf.
Michael-O,

4
Bardzo niedokładna odpowiedź. Ten Kevina jest naprawdę lepszy
Mike Aski

87

Szukasz ucieczek terminalnych . W szczególności, aby wyczyścić od pozycji kursora do początku linii:

echo -e "\033[1K"

Lub wszystko w linii, niezależnie od pozycji kursora:

echo -e "\033[2K"

Możesz także wykonywać różnego rodzaju inne sztuczki, korzystając z ucieczek terminalu.


6
Zakłada się, że terminal lub emulator jest zgodny z VT100 (co jest obecnie dość bezpiecznym założeniem).
Keith Thompson,

2
Jeśli chcesz usunąć coś, co właśnie echo, twoje poprzednie echo musi mieć flagę -n, w przeciwnym razie zostaniesz wysłany do nowej linii
djjeck

1
Jeśli chcesz napisać coś innego, w linii, którą wymazujesz, dodaj flagę -n do echa powyżej, albo przejdziesz do nowej linii zaraz po jej usunięciu. Dołącz także \ r do powyższego ciągu, w przeciwnym razie twoja nowa zawartość nie przejdzie na początek tego wiersza.
djjeck,

-1 | -eponieważ echoargument nie jest zgodny z POSIX + Nie podoba mi się sekwencja ucieczki. Wolę printfalbo tput.
LinuxSecurityFreak

@Vlastimil dlaczego miałbyś to głosować? OP nie poprosił o odpowiedź, którą byś chciał. Może powinien był sprecyzować, że ten -eparametr echonie jest zgodny z POSIX, ale nadal ...
souki

35

Jeśli chcesz wyczyścić linię, sugeruję użyć kombinacji zwrotu karetki, o którym wspominają ludzie i terminfo.

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

Spowoduje to zapis xyzzyxyzzy, następnie powrót do początku linii i wysłanie sekwencji „wyczyść do końca linii” do terminala, a następnie zapis foobar. Te -nmarki nie echo dodać przełamane po foobar.


4
Podoba mi się część tego konkretnego rozwiązania na przyszłość - użycie tput prawdopodobnie oznacza, że ​​będzie działało na każdym rodzaju terminala.
Amos Shapira,

2
Lepsze printf '%s\r%s%s' xyzzyxyzzy "$ceol" foobarpod względem przenośności i uniknięcia treści $ceolprzechodzących przez \xrozszerzenie.
Stéphane Chazelas

Najlepsza odpowiedź, choćby dlatego, że działa z dowolnie długimi liniami. Dzięki!
Raphael

działa idealnie. Ale jeśli zmienię rozmiar ekranu terminala mniejszego niż linia wyjściowa, stanie się bałagan.
K.Sopheak

11

Ty wyraźnie o to prosisz echo, ale ta prośba Cię przygnębia. Oto podejście wykorzystujące wbudowane printfpolecenie bash z rozszerzaniem nawiasów:

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

1
doskonały! dokładnie to, czego potrzebowałem
Omar S.

2
printf 'Status: rozpoczęty'; sleep 2s; printf '\ r'; printf 'Status: zaktualizowany'; sleep 2s; printf '\ r';
Omar S.

4

Oto przykład użycia echa bez opcji nowego wiersza -n i powrotu karetki \r .

bash nadpisuje linię terminala

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

Znacznik wyboru działa nawet na RHEL6. Fajnie dla czysto estetycznych edycji moich skryptów
oneindelijk

1

Zamiast tego echo -en "\r"możesz też uznać to printf "\r"polecenie za przydatne. W ten sposób możesz sformatować ciąg. na przykład:

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

Zwykle robię to również podczas pracy z powolnym analizowaniem plików, aby wyświetlić aktualnie trwającą nazwę pliku bez tworzenia listy


-1 | Być może chciałeś celowo stworzyć jedno-liniowy, ale w rzeczywistości jest to dobre tylko do testowania. Chciałbym napisać to poprawnie z nowymi wierszami.
LinuxSecurityFreak

0

Jako pytanie należy usunąć cały wiersz

Użyłem poniżej polecenia z kombinacją echoi seddo usunięcia wiersza

Po wykonaniu polecenia wynik będzie pusty. Póki linia nie zostanie zastąpiona żadną

Komenda

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

Oto przykład licznika, którego używam:

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 | Być może chciałeś celowo stworzyć jedno-liniowy, ale w rzeczywistości jest to dobre tylko do testowania. Chciałbym napisać to poprawnie z nowymi wierszami.
LinuxSecurityFreak

Następnie zrób to i dodaj nową odpowiedź. Lub zaproponuj edycję mojej odpowiedzi.
mikiemorales
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.