¿Cómo borrar la línea con eco?

60

Sé que podría eliminar los últimos tres caracteres con:

echo -ne '\b\b\b'

Pero, ¿cómo puedo eliminar una línea completa? Quiero decir que no quiero usar:

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 ... para eliminar una línea larga.

LanceBaynes
fuente
2
Para aquellos a quienes les gustaría escribir continuamente en la misma línea: echo -ne "\033[2K" ; printf "\r"ahora la línea está como nueva, como si nunca antes se hubiera escrito.
Hola Mundo
2
Estoy bastante seguro de que solo puedes usar echo -ne "\e[2K\r". Pero las secuencias de escape ANSI FTW, sin embargo.
Parthian Shot
Ver también ¿Por qué es printf mejor que echo?
Comodín el

Respuestas:

57

Puede usar \bo \rpara mover el cursor hacia atrás y luego sobrescribir el carácter impreso con un nuevo carácter. Tenga en cuenta que \bni \relimina los caracteres impresos. Simplemente mueve el cursor hacia atrás. \bmueve el cursor un carácter hacia atrás y \rmueve el cursor al comienzo de la línea.

Ejemplo: ambos

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

y

echo -e 'foooo\rbar'

imprimirá:

baroo

Si desea que se eliminen los caracteres, debe usar la siguiente solución:

echo -e 'fooooo\r     \rbar'

salida:

bar  

Extracto de 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.
lesmana
fuente
44
Sí, pero echo -e 'fooooooooo\rbarresuena barooooooo.
Mat
1
Sí, tiene usted razón. Tenga en cuenta que echo -e 'foooo\b\b\b\b\b\b\b\b\b\bbar'también hace eco baroo.
lesmana
Tan dulce, funciona incluso sin problemas printf.
Michael-O
44
Respuesta muy inexacta. El de Kevin es realmente mejor
Mike Aski
87

Estás buscando escapes de terminal . En particular, para borrar desde la posición del cursor hasta el comienzo de la línea:

echo -e "\033[1K"

O todo en la línea, independientemente de la posición del cursor:

echo -e "\033[2K"

Y también puedes hacer todo tipo de trucos geniales con salidas de terminal.

Kevin
fuente
66
Esto supone un terminal o emulador compatible con VT100 (que es una suposición bastante segura en estos días).
Keith Thompson
2
Si desea borrar algo que acaba de repetir, su eco anterior debe tener la bandera -n, o se lo enviará a una nueva línea
djjeck el
1
Si desea escribir algo más, en la línea que está borrando, agregue una bandera -n en el eco de arriba, o de lo contrario irá a una nueva línea justo después de eliminarla. Además, agregue un \ r a la cadena de arriba, o su nuevo contenido no irá al comienzo de esa línea.
djjeck
-1 | -ecomo echoargumento no es compatible con POSIX + No me gustan las secuencias de escape. O prefieres printfo tput.
LinuxSecurityFreak
@Vlastimil, ¿por qué rechazarías esto? OP no pidió una respuesta que le gustaría. Tal vez debería haber precisado que el -eparámetro echono es compatible con POSIX pero aún así ...
souki
35

Si desea borrar la línea, le sugiero que use una combinación del retorno de carro que la gente menciona y terminfo.

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

Esto escribirá xyzzyxyzzy, luego volverá al comienzo de la línea y enviará la secuencia "borrar al final de la línea" al terminal, luego escriba foobar. El -necho hace que no se agregue una nueva línea después del foobar.

Arcege
fuente
44
Me gusta el tipo de parte a prueba de futuro de esta solución específica: el uso de tput posiblemente significa que funcionará en cualquier tipo de terminal.
Amos Shapira
2
Mejor en cuanto printf '%s\r%s%s' xyzzyxyzzy "$ceol" foobara portabilidad y para evitar tener el contenido de $ceolpasar por la \xexpansión.
Stéphane Chazelas
La mejor respuesta es solo porque funciona con líneas arbitrariamente largas. ¡Gracias!
Raphael
trabajo perfecto Pero si redimensiono la pantalla del terminal más pequeña que la línea de salida, se vuelve desordenada.
K.Sopheak
11

Usted lo solicita explícitamente echo, pero esta solicitud lo inmoviliza. Aquí hay un enfoque que utiliza el printfcomando incorporado de bash con expansión de llaves:

printf 'fooooooooo' # 10 characters
printf '\r'; printf ' %0.s' {0..9} # 10 expansions of the space character
kojiro
fuente
1
¡Perfecto! exactamente lo que necesitaba
Omar S.
2
printf 'Estado: iniciado'; sleep 2s; printf '\ r'; printf 'Estado: actualizado'; sleep 2s; printf '\ r';
Omar S.
4

Aquí hay un ejemplo usando las opciones de retorno de línea -n y retorno de carro sin echo \r.

línea terminal de sobrescritura bash

#!/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"
Derek Soike
fuente
La marca de verificación funciona incluso en RHEL6. Agradable para ediciones puramente estéticas de mis guiones
oneindelijk
1

En lugar de echo -en "\r"usted también puede encontrar el printf "\r"comando como útil. De esta manera puede formatear la cadena. p.ej:

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

Por lo general, también lo hago cuando opero con un análisis lento de archivos para mostrar el nombre de archivo actualmente en progreso sin crear una lista

McPeppr
fuente
-1 | Tal vez quisiste hacer una frase intencionalmente, pero eso en realidad solo es bueno para probar. Lo volvería a escribir correctamente con nuevas líneas.
LinuxSecurityFreak
0

Como la pregunta es eliminar la línea completa

He usado el siguiente comando con la combinación de echoy sedpara eliminar la línea

Después de la ejecución del comando, el resultado estará vacío, ya que la línea se reemplazará por ninguna.

mando

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"
Praveen Kumar BS
fuente
-1

Aquí hay un ejemplo de temporizador de cuenta regresiva que uso:

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
mikiemorales
fuente
-1 | Tal vez quisiste hacer una frase intencionalmente, pero eso en realidad solo es bueno para probar. Lo volvería a escribir correctamente con nuevas líneas.
LinuxSecurityFreak
Luego, adelante, hazlo y agrega una nueva respuesta. O proponer una edición de mi respuesta.
mikiemorales