Je veux créer un chronomètre dans Bash, avec une fonction de pause. Il devrait afficher un compteur incrémentiel, comme celui-ci , mais le met en pause lorsque j'appuie sur le "p" clé.
Comment dois-je mettre cela en œuvre? Si j'attends la saisie de l'utilisateur avec read
, je ne peux pas actualiser le compteur à l'écran en même temps. Mettre le read
dans une boucle, avec un timeout, est mon meilleur plan jusqu'à présent, mais ce n'est pas trivial d'utiliser un timeout de moins d'une seconde, ce dont j'aurais besoin ici. (Ce n'est pas pris en charge par read
ou GNU timeout
.) Les interruptions fonctionneraient, mais j'aimerais prendre en charge des clés arbitraires comme "p" et "x". P >
Existe-t-il un moyen raisonnablement simple d'y parvenir?
3 Réponses :
J'ai fait un changement dans le code que vous faites référence.
while read char; do if [ $char == "p" ]; then if [ -z $(cat /tmp/pause) ];then echo 1 > /tmp/pause else echo > /tmp/pause fi char=0 fi done < /dev/stdin
Donc, ce que vous devez faire maintenant est un script shell qui attend le caractère "p" de stdin et écrit 1> / tmp / pause ou clean / tmp / pause pour mettre le chronomètre en pause ou fonctionner.
quelque chose comme:
... while [ true ]; do if [ -z $(cat /tmp/pause) ]; then STOPWATCH=$(TZ=UTC datef $DATE_INPUT $DATE_FORMAT | ( [[ "$NANOS_SUPPORTED" ]] && sed 's/.\{7\}$//' || cat ) ) printf "\r\e%s" $STOPWATCH sleep 0.03 fi done
compteur
ou si vous aimez spin
). readCommand
) sleep .1
et read -t.1
) function readCommand(){ lastCommand=$1 read -t.1 -n1 c; if [ "$c" = "p" ] then printf "\n\r"; return 0 fi if [ "$c" = "g" ] then printf "\n\r"; return 1 fi return $lastCommand } function spin(){ for i in / - \\ \| ; do printf "\r$i"; sleep .1; done } function countUp(){ currentCount=$1 return `expr $currentCount + 1` } function counter(){ countUp $count count=$? printf "\r$count" sleep .1; } command=1 count=0 while : do if [[ $command == 1 ]] then counter fi readCommand $command command=$? done
Le compteur s'arrêtera si l'utilisateur appuie sur 'p'
et continue si l'utilisateur appuie sur 'g'
p>
Script simple avec descripteur de fichier et redirection d'entrée simple, ne laissant aucun fichier temporaire à nettoyer. L'attente se fait en utilisant le paramètre read
-t
.
Your name, Sir? 2:12:17.153951623l Sir Kamil, we exit
Exemple de sortie:
counter() { while ! read -t 0.05 -n1 _; do printf '\r\t%s' "$(date +%T.%N)" done } { IFS= read -p "Your name, Sir?"$'\n' -r name echo >&3 } 3> >(counter "$tmp") echo "Sir $name, we exit"
Cela semble très prometteur - malheureusement, ne fonctionne pas sur BSD (OSX), qui ne prend pas en charge les délais décimaux pour lecture
. (Mais je n'ai pas spécifié OSX dans l'énoncé du problème.)
Hm, avez-vous timeout avec des nombres réels? Je pense que vous pouvez timeout 0.05 read -t -n1 _
... et n'oubliez pas de vérifier l'état de reutrn.
Quelque chose avec un processus en arrière-plan pour mettre à jour le compteur, puis le tuer si vous obtenez l'entrée de l'utilisateur?
Pourquoi fais-tu ça? Quelles sont vos limites? Est-ce que cela doit être fait en bash? Bien sûr, cela peut être fait dans bash mais ce ne serait probablement pas aussi raisonnablement simple que dans d’autres langages.
@brunorey - Ma préférence est de savoir comment le faire dans Bash, mais j'envisagerais d'autres solutions.