web-dev-qa-db-fra.com

Écraser la sortie précédente dans Bash au lieu de l'ajouter

Pour une minuterie bash, j'utilise ce code:

#!/bin/bash
sek=60
echo "60 Seconds Wait!"
echo -n "One Moment please "
while [ $sek -ge 1 ]
do
   echo -n "$sek "  
sleep 1
   sek=$[$sek-1]
done
echo
echo "ready!"

Cela me donne quelque chose comme ça

One Moment please: 60 59 58 57 56 55 ...

Existe-t-il une possibilité de remplacer la dernière valeur de seconde par la plus récente, de sorte que la sortie ne génère pas une trace importante, mais le compte à rebours des secondes comme un temps réel à une position? (J'espère que vous comprenez ce que je veux dire :))

20
NES
#!/bin/bash
sek=60
echo "60 Seconds Wait!"
echo -n "One Moment please "
while [ $sek -ge 1 ]
do
   echo -n "$sek" 

sleep 1
   sek=$[$sek-1]
   echo -en "\b\b"
done
echo
echo "ready!"
14
aneeshep

Identique à la réponse de aneshep, mais utilise Retour (\r) plutôt que Retour arrière (\b) car nous ne savons pas si la longueur sera toujours la même, par exemple. quand $sek < 10.

De même, votre premier echodoit utiliser $sek, et non pas du code codé 60.

Enfin, notez l'espace après le ....

#!/bin/bash
sek=60
echo "$sek Seconds Wait!"
while [ $sek -ge 1 ]
do
   echo -ne "One Moment please $sek ... \r"
   sleep 1
   sek=$[$sek-1]
done
echo
echo "ready!"
16
Mikel

Avec bash, vous pouvez utiliser la variable spéciale SECONDS.

#BASH
SECONDS=0;
while sleep .5 && ((SECONDS <= 60)); do 
    printf '\r%s: %2d' "One moment please" "$((60-SECONDS))"
done
printf '\n'
7
geirha

En plus des approches \r ou \b, il est possible d'utiliser le \033[2Kcaractère de contrôle , qui indique au terminal d'effacer toute la ligne. L’avantage de ceci par rapport à \b est qu’il n’est pas nécessaire de faire correspondre le nombre de \b au nombre de caractères que vous souhaitez supprimer, et comparé à \r, aucun caractère ne sera affiché à l’écran si la nouvelle ligne est plus courte. que l'ancien.

Vous trouverez ci-dessous un exemple d'application de cette question à la question. here est un exemple d'application associée permettant de créer une sortie similaire aux messages de démarrage. Dans cet exemple particulier, la minuterie disparaîtra une fois que la 0e seconde est atteinte et la ligne de la minuterie sera remplacée par "Prêt!" phrase.

#!/bin/bash
sek=60
echo "60 Seconds"

while ((sek--)); do
    printf "One moment please: %d" "$sek"
    sleep 1
    printf "\r%b" "\033[2K"
done
echo "Ready!"

Une autre solution consisterait à utiliser la commande dialog pour créer des dialogues simples en ligne de commande. La boîte de dialogue restera à l'écran pendant toute la durée du chronomètre et se mettra à jour avec la boucle. À la fin du temps, le chronomètre sera remplacé par le message "Prêt! Appuyez sur pour sortir" de manière transparente:

#!/bin/bash
sek=60
echo "60 Seconds"

while ((sek--)); do
    echo "$sek" | dialog --progressbox "Please wait" 10 25
    sleep 1
done
dialog --msgbox "Ready! Press <OK> to finish" 10 25
3

Pour ce faire, placez le retour chariot \r.

En une seule ligne de code, c'est possible avec echo -ne

for i in {60..1}; do echo -ne "One moment please: $i\r" && sleep 1; done

ou avec printf

for i in {60..1}; do printf "One moment please: $i\r" && sleep 1; done
1
Akif

C’est ce que j’ai trouvé après avoir lu ici et un peu plus, le liner:

SEC=101;for i in `seq $SEC -1 1`;do printf "\rNext in: %`expr length $SEC`ds" "$i";sleep 1;done;echo

Plus lisible:

#!/bin/bash
SEC=101

for i in `seq $SEC -1 1`;do
        printf "\rNext in: %`expr length $SEC`ds" "$i";
        sleep 1;
done
echo

Où SEC peut être défini sur n'importe quel entier positif et printf se chargera du remplissage approprié. Testé sous Ubuntu et cygwin.

1
Tod