112 votes

Comment supprimer et remplacer la dernière ligne dans le terminal en utilisant bash?

Je veux mettre en place une barre de progression montrant les secondes écoulées en bash. Pour ce faire, j'ai besoin d'effacer la dernière ligne affichée à l'écran (la commande "clear" efface tout l'écran, mais je dois effacer uniquement la ligne de la barre de progression et la remplacer par les nouvelles informations).

Le résultat final devrait ressembler à :

$ Temps écoulé 5 secondes

Ensuite, après 10 secondes, je veux remplacer cette phrase (à la même position à l'écran) par :

$ Temps écoulé 15 secondes

203voto

Derek Veit Points 775

Le retour chariot par lui-même ne fait que déplacer le curseur au début de la ligne. C'est correct si chaque nouvelle ligne de sortie est au moins aussi longue que la précédente, mais si la nouvelle ligne est plus courte, la ligne précédente ne sera pas complètement écrasée, par exemple :

$ echo -e "abcdefghijklmnopqrstuvwxyz\r0123456789"
0123456789klmnopqrstuvwxyz

Pour effacer réellement la ligne pour le nouveau texte, vous pouvez ajouter \033[K après le \r:

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

http://fr.wikipedia.org/wiki/Code_d'échappement_ANSI

3 votes

Cela fonctionne vraiment bien dans mon environnement. Toute connaissance de compatibilité?

22 votes

En Bash, au moins, cela peut être raccourci en \e[K au lieu de \033[K.

0 votes

Super réponse! Fonctionne parfaitement en utilisant puts de ruby. Maintenant, partie de ma boîte à outils.

123voto

Ken Points 23619

Echo un retour à la ligne avec \r

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

de man echo:

-n     ne pas imprimer le saut de ligne final
-e     activer l'interprétation des échappements en barre oblique inversée

\r     retour de chariot

21 votes

pour i in {1..100000}; faire echo -en "\r$i"; fait pour éviter l'appel à seq :-)

0 votes

Cela fait exactement ce dont j'ai besoin, merci !! Et l'utilisation de la commande seq gèle en effet le terminal :-)

11 votes

Lorsque vous utilisez des choses comme "for i in $(...)" ou "for i in {1..N}" vous générez tous les éléments avant d'itérer, c'est très inefficace pour de grandes entrées. Vous pouvez soit profiter des tuyaux : "seq 1 100000 | while read i; do ..." ou utiliser la boucle for de style c bash : "for ((i=0;;i++)); do ..."

21voto

Um. Points 38

La réponse de Derek Veit fonctionne bien tant que la longueur de la ligne ne dépasse jamais la largeur du terminal. Si ce n'est pas le cas, le code suivant empêchera la sortie de données indésirables :

avant que la ligne ne soit écrite pour la première fois, faire

tput sc

ce qui sauvegarde la position actuelle du curseur. Maintenant, chaque fois que vous voulez imprimer votre ligne, utilisez

tput rc
tput ed
echo "votre contenu ici"

pour d'abord revenir à la position du curseur sauvegardée, puis effacer l'écran du curseur vers le bas, et enfin écrire la sortie.

0 votes

Étrange, cela ne fait rien dans terminator. Savez-vous s'il y a des limitations de compatibilité?

1 votes

Note pour Cygwin: Vous devez installer le paquet "ncurses" pour utiliser "tput".

0 votes

Hm... Il semble que cela ne fonctionne pas si plus d'une ligne est dans la sortie. Cela ne fonctionne pas: tput sc # save cursor echo '' > sessions.log.json while [ 1 ]; do curl 'http://localhost/jolokia/read/*:type=Manager,*/activeSessio‌​ns,maxActiveSessions‌​' >> sessions.log.json echo '' >> sessions.log.json cat sessions.log.json | jq '.' tput rc;tput el # rc = restaure le curseur, el = efface jusqu'à la fin de la ligne sleep 1 done

4voto

Mikael S Points 2973

Utilisez le caractère de retour à la ligne :

echo -e "Foo\rBar" # Affichera "Bar"

0 votes

Cette réponse est la manière la plus simple. Vous pouvez même obtenir le même effet en utilisant: printf "Foo\rBar"

-2voto

Romuald Brunet Points 1062

La manière la plus simple est d'utiliser le caractère \r je suppose.

L'inconvénient est que vous ne pouvez pas avoir des lignes complètes, car il efface uniquement la ligne actuelle.

Exemple simple:

time=5
echo -n "Écoulé $time secondes"
sleep 10
time=15
echo -n "Écoulé $time secondes"

echo "\nTerminé"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X