Produz algo (em um loop) até que uma tecla seja pressionada

5

Estou tentando fazer um cronômetro e, quando o usuário pressionar Q, eu quero sair.

Encontrei dois scripts, um em que um relógio é exibido até que ctrl + z seja pressionado. E um script que sai se "q" for pressionado.

Eu tentei combiná-los, mas "read" parece estragar tudo.

A razão pela qual eu quero conseguir isso é que, se o usuário pressionar Q, o tempo decorrido será salvo em um arquivo.

Cronômetro:

BEGIN=$(date +%s)

echo Starting Stopwatch...

while true; do
   NOW=$(date +%s)
   let DIFF=$(($NOW - $BEGIN))
   let MINS=$(($DIFF / 60))
   let SECS=$(($DIFF % 60))
   let HOURS=$(($DIFF / 3600))
   let DAYS=$(($DIFF / 86400))

   # \r  is a "carriage return" - returns cursor to start of line
   printf "\r%3d Days, %02d:%02d:%02d" $DAYS $HOURS $MINS $SECS
   sleep 0.25
done

Sair no q:

while true; do
    echo -en "Press Q to exit \t\t: "
    read input
    if [[ $input = "q" ]] || [[ $input = "Q" ]] 
        then break 
    else 
        echo "Invalid Input."
    fi
done

PS: Eu sou muito novato nisso.

    
por gel 06.10.2016 / 22:55

2 respostas

4

Talvez isso ajude você. Eu integrei os dois, com pequenas modificações embora. Aqui está o resultado.

BEGIN=$(date +%s)

echo Starting Stopwatch...
echo Press Q to exit.

while true; do
    NOW=$(date +%s)
    let DIFF=$(($NOW - $BEGIN))
    let MINS=$(($DIFF / 60))
    let SECS=$(($DIFF % 60))
    let HOURS=$(($DIFF / 3600))
    let DAYS=$(($DIFF / 86400))

    # \r  is a "carriage return" - returns cursor to start of line
    printf "\r%3d Days, %02d:%02d:%02d" $DAYS $HOURS $MINS $SECS

# In the following line -t for timeout, -N for just 1 character
    read -t 0.25 -N 1 input
    if [[ $input = "q" ]] || [[ $input = "Q" ]]; then
# The following line is for the prompt to appear on a new line.
        echo
        break 
    fi
done

Como você pode ver, eu coloquei o segundo script no lugar do comando sleep no primeiro primeiro. O tempo limite em read agora tem a função de lapso de tempo. Observe que a opção -N é necessária para que read não espere Enter e reaja assim que a primeira tecla for pressionada.

    
por 06.10.2016 / 23:49
2

Inspirada em esta resposta , você pode usar read com a opção -t , para que aguarde apenas uma tempo especificado e não indefinidamente. O código abaixo combina os dois trechos que você postou:

#!/bin/bash

begin=$(date +%s)
echo "Starting Stopwatch... Press q to exit"
while true; do
   now=$(date +%s)
   diff=$(($now - $begin))
   mins=$(($diff / 60))
   secs=$(($diff % 60))
   hours=$(($diff / 3600))
   days=$(($diff / 86400))

   # \r  is a "carriage return" - returns cursor to start of line
   # with [2K we clear the current line
   printf "[2K\r%3d Days, %02d:%02d:%02d" $days $hours $mins $secs

   # -n 1 to get one character at a time, -t 0.1 to set a timeout 
   read -n 1 -t 0.1 input                  # so read doesn't hang
   if [[ $input = "q" ]] || [[ $input = "Q" ]] 
   then
      echo # to get a newline after quitting
      break
   fi
done
    
por 06.10.2016 / 23:45