Come modificare il contenuto di una riga sul terminale invece di scriverne una nuova?


24

Pertanto, quando wgetviene visualizzata una pagina Web, viene visualizzata una barra di stato che indica la quantità / i file scaricati. Sembra così:

25%[=============>______________________________________] 25,000 100.0K/s (i trattini bassi sono spazi; non riuscivo proprio a capire come ottenere più di uno spazio consecutivo)

Tuttavia, invece di scrivere un'altra riga su stdout e aggiungere un'altra barra di avanzamento, la aggiorna in questo modo:

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

E wgetnon è nemmeno l'unico esempio di questo. Ad esempio, quando installi qualcosa lesse poi esci, il tuo prompt originale è ancora lì, insieme al risultato di qualsiasi comando che hai eseguito in precedenza. È come se non te ne fossi mai andato.

Quindi, le mie domande sono: come si chiama, come posso implementarlo, funziona solo per una singola linea alla volta e posso usarlo in C?


5
Consiglio di leggere BashFAQ 44 . Potresti trovarlo interessante.
jw013,

Risposte:


32

Prima di tutto la tua domanda non ha nulla a che fare con bash ma con il terminale. Il terminale sta rispondendo per visualizzare il testo dei programmi e bash stesso non ha alcun controllo sui programmi una volta lanciato.

I terminali offrono sequenze di controllo per controllare colore, font, posizione del cursore e altro. Per un elenco di sequenze di terminali standardizzate, consultare http://www.termsys.demon.co.uk/vtansi.htm Ad esempio è possibile

  • posiziona il cursore all'inizio della riga
  • eliminare la riga in seguito
  • scrivi una nuova riga

per creare una barra di avanzamento.

Le sequenze di escape del terminale più avanzate dipendono in genere dal terminale, ad esempio funzionano solo con Eterm o xterm. ncurses - è una libreria di programmazione che consente di creare programmi interattivi con il terminale in modo da non dover utilizzare sequenze di escape.

Come sovrascrivere una linea esistente con sequenze di terminali

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

Come sovrascrivere una linea esistente senza sequenza terminale

Una soluzione semplice è quella di non scrivere una riga alla fine ma di scrivere il ritorno a capo, che in pratica reimposta il cursore all'inizio della riga, ad esempio:

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

Il \rritorno a capo o posiziona il cursore all'inizio della riga e consente di sovrascrivere il contenuto della riga.

Passa da un buffer all'altro come lessovi

Il comportamento di lessè anche dovuto a una funzionalità terminale più avanzata, la schermata alternativa:

Nella modalità VT102, ci sono sequenze di escape per attivare e disattivare un buffer dello schermo alternativo, che ha le stesse dimensioni dell'area di visualizzazione della finestra. Se attivata, la schermata corrente viene salvata e sostituita con la schermata alternativa. Il salvataggio delle linee fatte scorrere dalla parte superiore della finestra è disabilitato fino a quando non viene ripristinata la schermata normale. La voce term-cap (5) per xterm consente all'editor visivo vi (1) di passare alla schermata alternativa per la modifica e ripristinare la schermata all'uscita. Una voce di menu popup semplifica il passaggio tra le schermate normali e alternative per taglia e incolla.

http://rosettacode.org/wiki/Terminal_control/Preserve_screen elenca alcuni esempi su come farlo da soli, tramite tput o tramite alcune sequenze di escape.


15

Invece di usare il echoquale aggiunge automaticamente una nuova riga alla stringa, usa printf "%s\r" whatever- il ritorno a capo invia il cursore all'inizio della riga corrente. esempio:

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

a seconda del cursore del tuo terminale, potrebbe essere più piacevole farloprintf "\r%2d " $num
Glenn Jackman,
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.