Ik wil een voortgangsbalk implementeren die de verstreken seconden in bash weergeeft. Hiervoor moet ik de laatste regel op het scherm wissen (de opdracht “wissen” wist het hele scherm, maar ik hoef alleen de regel van de voortgangsbalk te wissen en deze te vervangen door de nieuwe informatie).
Het uiteindelijke resultaat zou er als volgt uit moeten zien:
$ Elapsed time 5 seconds
Na 10 seconden wil ik deze zin (op dezelfde positie in het scherm) vervangen door:
$ Elapsed time 15 seconds
Antwoord 1, autoriteit 100%
De regelterugloop alleen verplaatst de cursor alleen naar het begin van de regel. Dat is OK als elke nieuwe regel met uitvoer minstens zo lang is als de vorige, maar als de nieuwe regel korter is, wordt de vorige regel niet volledig overschreven, bijvoorbeeld:
$ echo -e "abcdefghijklmnopqrstuvwxyz\r0123456789"
0123456789klmnopqrstuvwxyz
Om de regel voor de nieuwe tekst te wissen, kunt u \033[K
toevoegen na de \r
:
$ echo -e "abcdefghijklmnopqrstuvwxyz\r\033[K0123456789"
0123456789
http://en.wikipedia.org/wiki/ANSI_escape_code
Antwoord 2, autoriteit 59%
echo een regelterugloop met \r
seq 1 1000000 | while read i; do echo -en "\r$i"; done
van man echo:
-n do not output the trailing newline
-e enable interpretation of backslash escapes
\r carriage return
Antwoord 3, autoriteit 11%
Het antwoord van Derek Veit werkt goed zolang de lijnlengte nooit de terminalbreedte overschrijdt. Als dit niet het geval is, zal de volgende code ongewenste uitvoer voorkomen:
doe voordat de regel voor de eerste keer wordt geschreven
tput sc
die de huidige cursorpositie opslaat. Gebruik nu wanneer u uw regel wilt afdrukken
tput rc
tput ed
echo "your stuff here"
om eerst terug te keren naar de opgeslagen cursorpositie, vervolgens het scherm van de cursor naar beneden te wissen en tenslotte de uitvoer te schrijven.
Antwoord 4, autoriteit 7%
De \033-methode werkte niet voor mij. De \r-methode werkt, maar wist eigenlijk niets, maar zet de cursor gewoon aan het begin van de regel. Dus als de nieuwe string korter is dan de oude, kun je de overgebleven tekst aan het einde van de regel zien. Uiteindelijk was tput de beste manier om te gaan. Het heeft andere toepassingen dan de cursor-dingen en het is vooraf geïnstalleerd in veel Linux & BSD-distributies, dus het zou voor de meeste bash-gebruikers beschikbaar moeten zijn.
#/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
Hier is een klein aftelscript om mee te spelen:
#!/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"
Antwoord 5, autoriteit 5%
In het geval dat de voortgangsuitvoer uit meerdere regels bestaat, of als het script het nieuwe regelteken al zou hebben afgedrukt, kunt u regels omhoog springen met zoiets als:
printf "\033[5A"
waardoor de cursor 5 regels omhoog springt. Daarna kun je alles overschrijven wat je nodig hebt.
Als dat niet zou werken, zou je printf "\e[5A"
of echo -e "\033[5A"
kunnen proberen, wat hetzelfde effect zou moeten hebben .
Kortom, met escape-reeksenkun je bijna alles besturen op het scherm.
Antwoord 6, autoriteit 2%
Gebruik het terugloopteken:
echo -e "Foo\rBar" # Will print "Bar"
Antwoord 7
Kan dit bereiken door een regelterugloop \r
te plaatsen.
In een enkele regel code met printf
for i in {10..1}; do printf "Counting down: $i\r" && sleep 1; done
of met echo -ne
for i in {10..1}; do echo -ne "Counting down: $i\r" && sleep 1; done