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.