¿Cómo cambiar el contenido de una línea en el terminal en lugar de escribir uno nuevo?

Entonces, cuando wget obtiene una página web, muestra una barra de estado que indica cuánto se descargan los files. Se parece a esto:

25%[=============>______________________________________] 25,000 100.0K/s (los guiones bajos son espacios; simplemente no pude encontrar la manera de get más de un espacio consecutivo allí)

Sin embargo, en lugar de escribir otra línea para stdout y agregar otra barra de progreso, la actualiza de esta manera:

50%[===========================>________________________] 50,000 100.0K/s

Y wget no es el único ejemplo de esto, tampoco. Por ejemplo, cuando canaliza algo en less y luego sale, su post original todavía está allí, junto con el resultado de los commands que ejecutó previamente. Es como si nunca te hubieras ido.

Entonces, mis preguntas son, ¿cómo se llama esto, cómo lo implemento, solo funciona para una sola línea a la vez, y puedo usar esto en C?

Antes que nada, tu pregunta no tiene nada que ver con bash, sino con la terminal. El terminal está respondiendo para mostrar el text de los progtwigs y bash no tiene control sobre los progtwigs una vez que se lanzaron.

Los terminales ofrecen secuencias de control para controlar el color, la fuente, la position del cursor y más. Para get una list de secuencias de terminales estandarizadas, consulte http://www.termsys.demon.co.uk/vtansi.htm . Puede, por ejemplo,

  • posiciona el cursor al comienzo de la línea
  • eliminar la línea después
  • escribe una nueva linea

para crear una barra de progreso.

Las secuencias de escape de terminal más avanzadas son típicamente dependientes del terminal, por ejemplo, funcionan solo con Eterm o xterm. ncurses – es una biblioteca de progtwigción que crea progtwigs interactivos con el terminal para que no tenga que usar secuencias de escape.

Cómo sobrescribir una línea existente con secuencias de terminal

 echo long text sleep 1 printf "\033[1A" # move cursor one line up printf "\033[K" # delete till end of line echo foo 

Cómo sobrescribir una línea existente sin secuencia de terminal

Una solución simple es no escribir una nueva línea al final sino escribir retorno de carro, que básicamente restablece el cursor al comienzo de la línea, por ejemplo:

 echo -n first sleep 1 echo -ne "\rsecond" echo 

El retorno del carro colocará el cursor al comienzo de la línea y le permitirá sobrescribir el contenido de la línea.

Cambiar entre almacenamientos intermedios como less o vi

El comportamiento de less también se debe a una function de terminal más avanzada, la pantalla alternativa:

En el modo VT102, existen secuencias de escape para activar y desactivar un búfer de pantalla alternativo, que es del mismo tamaño que el área de visualización de la window. Cuando se activa, la pantalla actual se guarda y se reemplaza con la pantalla alternativa. El almacenamiento de líneas desplazadas desde la parte superior de la window se desactiva hasta que se restablezca la pantalla normal. La input de term-cap (5) para xterm permite que el editor visual vi (1) cambie a la pantalla alternativa para editar y restaurar la pantalla al salir. Una input del menu emergente hace que sea sencillo cambiar entre las pantallas normal y alternativa para cortar y pegar.

http://rosettacode.org/wiki/Terminal_control/Preserve_screen enumera algunos ejemplos de cómo hacerlo usted mismo, ya sea a través de tput o mediante algunas secuencias de escape.

En lugar de usar echo que agrega automáticamente una nueva línea a la cadena, use printf "%s\r" whatever – el retorno de carro envía el cursor al comienzo de la línea actual. ejemplo:

 seq 1 15 | while read num; do printf "%2d\r" $num; sleep 1; done; echo ""