2016-01-15 2 views
3

У меня есть сценарий bash, который запрашивает у пользователя их данные.BASH - Timed Input - Показать обратный отсчет

Я устанавливаю предел того, как долго мы ждем ввода. Я нашел это, и мне кажется, что я хочу.

timelimit=5 
echo -e " You have $timelimit seconds\n Enter your name quickly: \c" 
name="" 
read -t $timelimit name 
#read -t $timelimit name <&1 
# for bash versions bellow 3.x 
if [ ! -z "$name" ] 
then 
echo -e "\n Your name is $name" 
else 
echo -e "\n TIME OUT\n You failed to enter your name" 
fi 

Это показывает «У вас есть 5 секунд ...» какой-либо способ для обновления вывода, так он показывает 4,3,2,1 и т.д., как это отсчитывает?

Благодаря

ответ

2

Это должно работать, а не перезаписывать ввод, немного более долго наматывается, чем другие решения.

#!/bin/bash 

abend() 
{  
     stty sane 
     exit 
     #Resets stty and then exits script 
} 

DoAction(){ 

     stty -echo 
     #Turn off echo 
     tput sc 
     #Save cursor position 
     echo -ne "\033[0K\r" 
     # Remove previous line 
     tput cuu1 
     #Go to previous line 
     tput el 
     #clear to end of line 
     echo "You have $(($time-$count)) seconds" 
     #Echo timer 
     echo -n "$Keys" 
     #Echo currently typed text 
     stty echo 
     #turn echo on 
     tput rc 
     #return cursor 
} 


main() 
{ 
trap abend SIGINT # Trap ctrl-c to return terminal to normal 
stty -icanon time 0 min 0 -echo 
#turn of echo and set read time to nothing 
keypress='' 

time=5 
echo "You have $time seconds" 
while Keys=$Keys$keypress; do 
     sleep 0.05 
     read keypress && break 
     ((clock = clock + 1)) 
     if [[ clock -eq 20 ]];then 
       ((count++)) 
       clock=0 
       DoAction $Keys 
     fi 
     [[ $count -eq $time ]] && echo "you have run out of time" && abend 



done 

stty sane 
echo Your username was $Keys 
echo "Thanks for using this script." 
exit 0 
} 

main 
+0

Спасибо, что это работает, но есть задержка при вводе имени. есть идеи ? – Rocket

+0

Это почти идеально;) Только основная проблема у меня есть, если тайм-аут составляет 10 секунд или больше. Затем изменяется формулировка: «У вас есть 9 секунд». Вы получаете дополнительные s на конце. – Rocket

+0

@ Обновлено Rocket – 123

0

Я хотел бы предложить, либо используя цикл, который печатает у вас есть секунды, а затем спит в течение одной секунды. Это даст вам то, что вы ищете.

В качестве альтернативы вы можете написать 5 операторов печати с функцией спать в течение 1 секунды между каждым оператором и уменьшить вашу переменную $ timelimit на 1 после каждой печатной строки.

Вот отличная ссылка, которая поможет вам получить то, что вы хотите. http://www.cyberciti.biz/faq/linux-unix-sleep-bash-scripting/

+1

Как вы могли бы использовать 'read' в то время как цикл работает? –

+0

Это хороший момент, я интерпретировал этот вопрос как вопрос о том, как распечатать обратный отсчет, а не как распечатать обратный отсчет, а также проверить ввод в течение этого времени. У меня есть идеи, как использование чтения в цикле будет работать, но поскольку я никогда не тестировал что-то подобное, я не буду спекулировать. – clipsett

1

Это похоже на работу:

$ cat test.sh 
total=5 # total wait time in seconds 
count=0 # counter 
while [ ${count} -lt ${total} ] ; do 
    tlimit=$(($total - $count)) 
    echo -e "\rYou have ${tlimit} seconds to enter your name: \c" 
    read -t 1 name 
    test ! -z "$name" && { break ; } 
    count=$((count+1)) 
done 
if [ ! -z "$name" ] ; then 
    echo -e "\nyour name is $name" 
else 
    echo -e "\ntime out" 
fi 
+0

Не будет перезаписывать то, что вы печатаете? – 123

+0

@ 123 результат все равно будет правильным (stdin - буферизирован в строке), однако да: на терминале вы увидите странные вещи. –

+0

@AndreaCorbellini Любая идея, почему только цифры испортили мой ответ. Конечный результат верен, но, похоже, кошмар сохраняет цифры в правильном порядке, когда эхом выступает в «Doaction» и занимает около 2 секунд, чтобы разобраться в себе. – 123

1
#!/bin/bash 

timelimit=6 
name="" 

for ((i = 1 ; i <= $timelimit; i++)); do 
     echo -ne "\rYou have $(expr $timelimit - $i) seconds. Enter your name quickly: \c" 
     [ ! -z "$name" ] && { break ; } 
     read -t 1 name 
done 

if [ -z "$name" ]; then 
     echo -e "\n TIME OUT\n You failed to enter your name" 
else 
     echo -e "\n Your name is $name" 
fi 

это должно работать

+0

Кажется, что это работает, но если вы приостановите курсор, переместитесь в начало ввода! любая идея почему? – Rocket

1

Это прекрасно работает и быстро для меня:

#!/bin/bash 
#Sets starttimestamp 
starttime=$(date +%s) 
#Sets timeout 
timeout=5 
#sets successflag default to false 
success=false 

#Save Cursorposition 
echo -n -e "\033[s" 

#While time not up 
while [ $(($starttime+$timeout)) -gt $(date +%s) ] ; do 
     #Return to saved Cursorpositon 
     echo -n -e "\033[u" 
     #Display time left 
     echo "$(((starttime+timeout)-$(date +%s))) seconds left" 
     #Ask for 1 char then go on in loop make it look like an ongoing input by adding the user variable to the prompt 
     if read -p foo="Username: $user" -n 1 -t 1 c ; then 
       #If user hits return in time c will be empty then break out of loop and set success true 
       if [[ $c == "" ]] ; then 
         success=true 
         break 
       fi 
       # Append latest character to user variable 
       user=${user}${c} 
       unset c 
     fi 
done 

if $success ; then 
     echo "Yiha!" 
else 
     echo "Too late!" 
fi 
Смежные вопросы