Chcę zaimplementować pasek postępu pokazujący upływające sekundy w bash. W tym celu muszę wykasować ostatnią linię wyświetlaną na ekranie (polecenie „wyczyść” wymazuje cały ekran, ale muszę wymazać tylko linię paska postępu i zastąpić ją nowymi informacjami).
Efekt końcowy powinien wyglądać następująco:
$ Elapsed time 5 seconds
Następnie po 10 sekundach chcę zamienić to zdanie (w tej samej pozycji na ekranie) przez:
$ Elapsed time 15 seconds
for i in {1..100000}; do echo -en "\r$i"; done
aby uniknąć kolejnego wezwania :-)Sam powrót karetki przenosi tylko kursor na początek wiersza. To jest OK, jeśli każdy nowy wiersz wyjścia jest co najmniej tak długi jak poprzedni, ale jeśli nowy wiersz jest krótszy, poprzednia linia nie zostanie całkowicie nadpisana, np .:
Aby rzeczywiście wyczyścić wiersz nowego tekstu, możesz dodać
\033[K
po\r
:http://en.wikipedia.org/wiki/ANSI_escape_code
źródło
\e[K
zamiast\033[K
.\033[G
io\r
wcześniej,\033[K
choć oczywiście\r
jest to znacznie prostsze. Również invisible-island.net/xterm/ctlseqs/ctlseqs.html zawiera więcej szczegółów niż Wikipedia i pochodzi od programisty xterm.Odpowiedź Dereka Veita działa dobrze, o ile długość linii nigdy nie przekracza szerokości terminala. Jeśli tak nie jest, poniższy kod zapobiegnie wysyłaniu śmieci:
zanim wiersz zostanie napisany po raz pierwszy, zrób
który zapisuje aktualną pozycję kursora. Teraz, kiedy chcesz wydrukować swoją linię, użyj
aby najpierw powrócić do zapisanej pozycji kursora, następnie wyczyść ekran od kursora do dołu, a na koniec zapisz wynik.
źródło
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
tput ed
zamiasttput el
. Zastosowano przykład @ Umed
(być może naprawił go po tym, jak skomentowałeś).Metoda \ 033 nie zadziałała dla mnie. Metoda \ r działa, ale tak naprawdę niczego nie kasuje, po prostu umieszcza kursor na początku wiersza. Więc jeśli nowy ciąg jest krótszy niż stary, możesz zobaczyć pozostały tekst na końcu linii. Ostatecznie tput był najlepszą drogą. Ma inne zastosowania poza funkcjami kursora, a ponadto jest preinstalowany w wielu dystrybucjach Linuksa i BSD, więc powinien być dostępny dla większości użytkowników basha.
Oto mały skrypt odliczający do gry:
źródło
W przypadku, gdy wynik postępu jest wieloliniowy lub skrypt już wypisałby znak nowego wiersza, możesz przeskoczyć linie w górę za pomocą czegoś takiego:
printf "\033[5A"
co spowoduje, że kursor przeskoczy o 5 linii w górę. Następnie możesz nadpisać wszystko, czego potrzebujesz.
Jeśli to nie zadziała, możesz spróbować
printf "\e[5A"
lubecho -e "\033[5A"
, co powinno przynieść ten sam efekt.Zasadniczo dzięki sekwencjom ucieczki możesz kontrolować prawie wszystko na ekranie.
źródło
tput cuu 5
, gdzie 5 to liczba rzędów (cuu
aby przejść w górę,cud
aby przejść w dół).Użyj znaku powrotu karetki:
źródło
Można to osiągnąć poprzez umieszczenie powrotu karetki
\r
.W jednej linii kodu z
printf
lub z
echo -ne
źródło