Come eliminare e sostituire l’ultima riga nel terminale usando bash?

Vorrei implementare una barra di avanzamento che mostra trascorso secondi in bash. Per questo, ho bisogno di cancellare l’ultima riga visualizzata sullo schermo (comando “clear” cancella tutto lo schermo, ma ho bisogno di cancellare solo la riga della barra di avanzamento e sostituirla con la nuova informazione).

Risultato finale dovrebbe assomigliare a questo:

$ Elapsed time 5 seconds

Poi dopo 10 secondi voglio sostituire questa frase (nella stessa posizione sullo schermo) da:

$ Elapsed time 15 seconds
InformationsquelleAutor Debugger | 2010-03-05

 

8 Replies
  1. 104

    eco un ritorno a capo con \r

    seq 1 1000000 | while read i; do echo -en "\r$i"; done

    da uomo eco:

    -n     do not output the trailing newline
    -e     enable interpretation of backslash escapes
    
    \r     carriage return
    • for i in {1..100000}; do echo -en "\r$i"; done per evitare la sequenza di chiamata 🙂
    • Questo fa esattamente quello che ho bisogno, grazie !! E l’uso del comando seq, infatti, blocca il termianl 🙂
    • Quando si utilizza cose come “for i in $(…)” o “for i in {1..N}” si generano tutti gli elementi prima iterazione, che è molto inefficiente per i grandi ingressi. Si può prendere vantaggio di tubi: “seq 1 100000 | mentre leggi i; fare …” o usare la bash, c-stile per il ciclo: “for ((i=0;;i++)); do …”
    • Grazie Douglas e tokland – sebbene la sequenza di produzione non era parte della domanda ho cambiato per tokland più efficiente tubo
    • Così come le buone vecchie macchine da scrivere.
    • La mia stampante a matrice è completamente rovinare la mia carta. Si continua a incepparsi punti sullo stesso pezzo di carta che non c’è più, quanto tempo di esecuzione del programma?
    • come fare la stessa cosa con php e stdout?

  2. 171

    Il ritorno a capo da solo sposta il cursore all’inizio della riga. Che è OK, se ogni nuova linea di uscita è lunga almeno quanto il precedente, ma se la nuova linea è più corta, la riga precedente non sarà completamente sovrascritto, ad esempio:

    $ echo -e "abcdefghijklmnopqrstuvwxyz\r0123456789"
    0123456789klmnopqrstuvwxyz

    Effettivamente cancella la linea per il nuovo testo, è possibile aggiungere \033[K dopo il \r:

    $ echo -e "abcdefghijklmnopqrstuvwxyz\r\033[K0123456789"
    0123456789

    http://en.wikipedia.org/wiki/ANSI_escape_code

    • Questo funziona molto bene nel mio ambiente. Qualsiasi conoscenza di compatibilità?
    • In Bash, almeno, che può essere abbreviato a \e[K invece di \033[K.
    • Grande risposta!!! Funziona perfettamente utilizzando mette da ruby. Ora parte del mio toolkit.
    • +1 per cancellare il testo
    • Pixel Sviluppatore: Grazie per aver cercato di migliorare, ma la modifica non è corretto. La restituzione deve avvenire prima di spostare il cursore all’inizio della riga, quindi il kill cancella tutto dalla posizione del cursore fino alla fine, lasciando l’intera riga vuota, che è lo scopo. Hai messo quelli che all’inizio di ogni nuova linea, allo stesso modo di Ken risposta, così che è scritto su una riga vuota.
    • Stavo usando zshell che potrebbe avere un comportamento differente. Devo verificare la mia ipotesi.
    • Questo dovrebbe sicuramente è stata la risposta.
    • Solo per la cronaca, si può anche fare \033[G io.o. \r prima \033[K anche se, ovviamente, \r è molto più semplice. Anche invisible-island.net/xterm/ctlseqs/ctlseqs.html fornisce ulteriori dettagli rispetto a Wikipedia e viene da xterm sviluppatore.
    • Questa è la risposta che stavo cercando. Deselezionando la linea di conto per imprevedibili successive lunghezza della linea è il punto chiave.

  3. 17

    Derek Veit risposta funziona bene fintanto che la lunghezza della linea non supera mai il terminale di larghezza. Se questo non è il caso, il seguente codice evitare spazzatura di uscita:

    prima riga è scritto per la prima volta, fare

    tput sc

    che consente di salvare la posizione corrente del cursore. Ora ogni volta che si desidera stampare la riga, utilizzare

    tput rc
    tput ed
    echo "your stuff here"

    prima di tornare a salvato nella posizione del cursore, quindi deselezionare lo schermo da cursore verso il basso, e, infine, scrivere l’output.

    • Strano, questo non fa nulla, in terminator. Sapete se ci sono limitazioni di compatibilità?
    • Nota per Cygwin: È necessario installare il pacchetto “ncurses” usare “tput”.
    • Hm… non Sembra funzionare se più di una riga è in uscita. Questo non funziona: tput sc # save cursor echo '' > sessions.log.json while [ 1 ]; do curl 'http://localhost/jolokia/read/*:type=Manager,*/activeSessions,maxActiveSessions' >> sessions.log.json echo '' >> sessions.log.json cat sessions.log.json | jq '.' tput rc;tput el # rc = restore cursor, el = erase to end of line sleep 1 done
    • È necessario utilizzare tput ed piuttosto che tput el. @Um esempio utilizzato ed (forse si fissa dopo che hai commentato).
    • Cordiali saluti, Ecco l’elenco di tput comandi i Colori e il Movimento del Cursore Con tput
  4. 11

    L’ \033 metodo non ha funzionato per me. Il \r metodo funziona, ma in realtà non cancella nulla, semplicemente sposta il cursore all’inizio della riga. Quindi, se la nuova stringa è più corta di quella vecchia, è possibile vedere i resti del testo alla fine della riga. Alla fine tput è il modo migliore per andare. Ha altri usi oltre il cursore roba più viene pre-installato in molti Linux & distribuzioni BSD e quindi dovrebbe essere disponibile per la maggior parte bash utenti.

    #/bin/bash
    tput sc # save cursor
    printf "Something that I made up for this string"
    sleep 1
    tput rc;tput el # rc = restore cursor, el = erase to end of line
    printf "Another message for testing"
    sleep 1
    tput rc;tput el
    printf "Yet another one"
    sleep 1
    tput rc;tput el

    Ecco un piccolo conto alla rovescia script per giocare:

    #!/bin/bash
    timeout () {
        tput sc
        time=$1; while [ $time -ge 0 ]; do
            tput rc; tput el
            printf "$2" $time
            ((time--))
            sleep 1
        done
        tput rc; tput ed;
    }
    
    timeout 10 "Self-destructing in %s"
    • Che cancella tutta la linea, infatti, il problema non brilla troppo per me :'(
  5. 5

    Nel caso In cui il progresso è uscita multi linea, o la sceneggiatura sarebbe già stampato il carattere di nuova riga, è possibile saltare le linee con qualcosa come:

    printf "\033[5A"

    che farà il cursore per passare 5 linee. Si può sovrascrivere qualsiasi cosa avete bisogno.

    Se questo non funziona si può provare printf "\e[5A" o echo -e "\033[5A", che dovrebbe avere lo stesso effetto.

    In sostanza, con le sequenze di escape è possibile controllare quasi tutto lo schermo.

  6. 4

    Utilizzare il carattere di ritorno a capo:

    echo -e "Foo\rBar" # Will print "Bar"
    • Questa risposta è la più semplice. Si può anche ottenere lo stesso effetto utilizzando: printf “Pippo\rBar”
  7. 1

    Può ottenere che l’immissione di ritorno \r.

    In una singola riga di codice con printf

    for i in {10..1}; do printf "Counting down: $i\r" && sleep 1; done

    o con echo -ne

    for i in {10..1}; do echo -ne "Counting down: $i\r" && sleep 1; done
  8. -2

    Il modo più semplice è quello di utilizzare il \r carattere credo.

    Lo svantaggio è che non è possibile disporre di linee complete, come si cancella solo la riga corrente.

    Semplice esempio:

    time=5
    echo -n "Elapsed $time seconds"
    sleep 10
    time=15
    echo -n "Elapsed $time seconds"
    
    echo "\nDone"
    • Um, ma il tuo esempio non eliminare e sostituire l’ultima riga, che è quello che l’OP ha chiesto.

Lascia un commento