Как сделать обратный отсчет в реальном времени в Bash, принимая пользовательский ввод

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

readFile(){
    linenumber=1
    end=10
    while  [ $linenumber -lt 18 ];do
        for (( i=0; i<=10; i++ )); do
            echo -ne "Time Remaining: $(expr $end - $i)\033[0K\r"
            sleep 1
            sed -n "$linenumber, $((linenumber + 5))p" < QuestionBank.txt            
            echo
            echo
            echo -n "Please Choose an Asnwer: "
            read -t 1 -n 1 answer
            echo
        done
        linenumber=$((linenumber + 6))
    done
}

вот мой код

Я ожидал, что он будет работать так, как показано на рисунке выше, но каждую секунду он снова печатает весь вывод.

Я не уверен, что в bash это будет легко сделать. Bash не очень хорош для ожидания ввода и одновременного изменения терминала. Вероятно, это можно было бы сделать с помощью tput, но результат, скорее всего, будет очень ошибочным.

user24246119 10.07.2024 14:21
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
73
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы ищете что-то вроде этого:

tput smcup
trap 'tput rmcup' EXIT
while question=$(head -n 6 <&3); [[ $question ]]; do
  for ((t = 10; t >= 0; t--)); do
    tput clear
    echo Time remaining: $t seconds
    echo
    echo "$question"
    echo
    read -p 'Your answer: ' -t 1 -n 1 answer && break
  done
  # TODO check $t and do something with $answer
done 3<QuestionBank.txt
Ответ принят как подходящий

Если вы хотите очистить экран и (повторно) распечатать первую строку консоли, вы можете использовать clear:

$ cat timer.clear
#!/bin/bash

unset answer
timer=5

while ((timer > 0))
do
    clear                                     # clear console and reset to first line

    echo "Time Remaining: ${timer} seconds"
    echo ""
    cat QuestionBank.txt
    echo ""

    read -t1 -n1 -p "Choose your option: " answer && break

    (( timer-- ))
done

echo ""
echo "############"
typeset -p answer

Берем на тест-драйв:

  • время первого вызова истекает через 5 секунд
  • второй вызов выходит из цикла после выбора «b»
  • обратите внимание, что каждый проход цикла очищает всю консоль и начинается заново со строки 1.

Если вы не хотите очищать всю консоль при каждом проходе цикла, есть множество способов сделать это с помощью tput. Одна идея:

$ cat timer.tput
#!/bin/bash

unset answer
timer=5

tput sc                                       # save current cursor location in console

while ((timer > 0))
do
    tput rc                                   # move cursor to save point created by "tput sc"
    tput ed                                   # clear everything from here 'down' to end of console

    echo "Time Remaining: ${timer} Seconds"
    echo ""
    cat QuestionBank.txt
    echo ""

    read -t1 -n1 -p "Choose your option: " answer && break

    (( timer-- ))
done

echo ""
echo "############"
typeset -p answer

Берем на тест-драйв:

  • время первого вызова истекает через 5 секунд
  • второй вызов выходит из цикла после выбора «b»
  • обратите внимание, что при каждом проходе цикла мы возвращаемся к тому месту, где начался текущий вызов; все, что отображалось в консоли до текущего вызова, по-прежнему видно

Другие вопросы по теме