Come eliminare la linea con l'eco?


60

So che potrei cancellare gli ultimi tre caratteri con:

echo -ne '\b\b\b'

Ma come posso cancellare una linea intera? Voglio dire che non voglio usare:

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'

... ecc ... per cancellare una linea lunga.


2
Per coloro che vorrebbero scrivere continuamente sulla stessa riga: echo -ne "\033[2K" ; printf "\r"ora la riga è come nuova, come se non fosse mai stata scritta prima.
Ciao mondo,

2
Sono abbastanza sicuro che puoi semplicemente usare echo -ne "\e[2K\r". Ma le sequenze di escape ANSI FTW, tuttavia.
Parthian Shot

Risposte:


57

È possibile utilizzare \bo \rper spostare indietro il cursore e quindi sovrascrivere il carattere stampato con un nuovo carattere. Si noti che né \b\relimina i caratteri stampati. Sposta semplicemente il cursore indietro. \bsposta il cursore indietro di un carattere e \rsposta il cursore all'inizio della riga.

Esempio: entrambi

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

e

echo -e 'foooo\rbar'

stamperà:

baroo

Se si desidera eliminare i caratteri, è necessario utilizzare la seguente soluzione alternativa:

echo -e 'fooooo\r     \rbar'

produzione:

bar  

Estratto da 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
Sì, ma fa echo -e 'fooooooooo\rbareco barooooooo.
Mat

1
Si hai ragione. Si noti che echo -e 'foooo\b\b\b\b\b\b\b\b\b\bbar'anche echi baroo.
lesmana,

Così dolce, funziona anche perfettamente printf.
Michael-O,

4
Risposta molto imprecisa. Quello di Kevin è davvero migliore
Mike Aski,

88

Stai cercando evasioni terminali . In particolare, per cancellare dalla posizione del cursore all'inizio della riga:

echo -e "\033[1K"

O tutto sulla linea, indipendentemente dalla posizione del cursore:

echo -e "\033[2K"

E puoi fare anche tutti i tipi di altri trucchi con le fughe del terminale.


6
Ciò presuppone un terminale o emulatore compatibile VT100 (che è un presupposto abbastanza sicuro in questi giorni).
Keith Thompson,

2
Se vuoi cancellare qualcosa che hai appena fatto eco, la tua eco precedente deve avere il flag -n, o verrai inviato a una nuova riga
djjeck,

1
Se vuoi scrivere qualcos'altro, sulla riga che stai cancellando, aggiungi un flag -n sull'eco sopra, altrimenti passerai a una nuova riga subito dopo averla eliminata. Inoltre, aggiungi a \ r alla stringa sopra o il tuo nuovo contenuto non andrà all'inizio di quella riga.
Djjeck,

-1 | -epoiché l' echoargomento non è conforme a POSIX + Non mi piacciono le sequenze di escape. O preferisci printfo tput.
LinuxSecurityFreak

@Vlastimil perché dovresti sottovalutare questo? OP non ha chiesto una risposta che desideri. Forse avrebbe dovuto precedere che il -eparametro echonon è conforme a POSIX ma comunque ...
souki

35

Se vuoi cancellare la linea, allora ti suggerisco di usare una combinazione del ritorno a capo che le persone stanno citando e terminfo.

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

Questo scriverà xyzzyxyzzy, quindi tornerà all'inizio della riga e invierà la sequenza "cancella alla fine della riga" al terminale, quindi scriverà foobar. L' -neco non aggiunge una nuova riga dopo il foobar.


4
Mi piace il tipo di parte a prova di futuro di questa soluzione specifica: l'uso di tput probabilmente significa che funzionerà su qualsiasi tipo di terminale.
Amos Shapira,

2
Meglio come printf '%s\r%s%s' xyzzyxyzzy "$ceol" foobarper la portabilità e per evitare che il contenuto di $ceolpassare attraverso \xl'espansione.
Stéphane Chazelas,

La migliore risposta se non altro perché funziona con linee arbitrariamente lunghe. Grazie!
Raffaello,

lavoro perfetto. Ma se ridimensiono lo schermo del terminale più piccolo della linea di uscita, diventa disordinato.
K.Sopheak

11

Lo chiedi esplicitamente echo, ma questa richiesta ti blocca. Ecco un approccio che utilizza il printfcomando incorporato di bash con espansione di parentesi graffe:

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

1
Perfetto! esattamente quello di cui avevo bisogno
Omar S.

2
printf 'Status: avviato'; sleep 2s; printf '\ r'; printf 'Status: aggiornato'; sleep 2s; printf '\ r';
Omar S.

4

Ecco un esempio che utilizza echo no newline -n e opzioni di ritorno a \r capo.

bash sovrascrive la linea terminale

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

Il segno di spunta funziona anche su RHEL6. Bello per le modifiche puramente estetiche dei miei script
oneindelijk

1

Invece di echo -en "\r"te potresti anche trovare printf "\r"utile il comando. In questo modo è possibile formattare la stringa. per esempio:

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

Di solito lo faccio anche quando opero con l'analisi dei file lenti per visualizzare il nome file attualmente in corso senza creare un elenco


-1 | Forse volevi realizzare intenzionalmente un one-liner, ma in realtà è buono solo per i test. Lo riscriverei correttamente con nuove righe.
LinuxSecurityFreak

0

Come domanda è eliminare l'intera riga

Ho usato sotto il comando con la combinazione di echoe sedper eliminare la riga

Dopo l'esecuzione del comando, il risultato sarà vuoto, poiché la riga verrà sostituita con nessuna

comando

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

Ecco un esempio di timer per il conto alla rovescia che utilizzo:

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 | Forse volevi realizzare intenzionalmente un one-liner, ma in realtà è buono solo per i test. Lo riscriverei correttamente con nuove righe.
LinuxSecurityFreak

Quindi, vai avanti e fallo e aggiungi una nuova risposta. O proponi una modifica della mia risposta.
Mikiemorales,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.