Bash: Как завершить бесконечный цикл нажатием любой клавиши? - PullRequest
25 голосов
/ 14 марта 2011

Мне нужно написать бесконечный цикл, который останавливается при нажатии любой клавиши.

К сожалению, этот цикл повторяется только при нажатии клавиши.

Идеи, пожалуйста?

#!/bin/bash

count=0
while : ; do

    # dummy action
    echo -n "$a "
    let "a+=1"

    # detect any key  press
    read -n 1 keypress
    echo $keypress

done
echo "Thanks for using this script."
exit 0

Ответы [ 4 ]

33 голосов
/ 14 марта 2011

Вам необходимо перевести стандартный вход в неблокирующий режим.Вот пример, который работает:

#!/bin/bash

if [ -t 0 ]; then stty -echo -icanon -icrnl time 0 min 0; fi

count=0
keypress=''
while [ "x$keypress" = "x" ]; do
  let count+=1
  echo -ne $count'\r'
  keypress="`cat -v`"
done

if [ -t 0 ]; then stty sane; fi

echo "You pressed '$keypress' after $count loop iterations"
echo "Thanks for using this script."
exit 0

Редактировать 2014/12/09: Добавьте флаг -icrnl к stty, чтобы правильно перехватить клавишу Return, используйте cat -vвместо read для захвата пробела.

Возможно, что cat читает более одного символа, если он достаточно быстро передает данные;если не соответствует желаемому поведению, замените cat -v на dd bs=1 count=1 status=none | cat -v.

8 голосов
/ 14 марта 2011

read имеет параметр времени ожидания -t, который можно использовать. Выполните неблокирующую проверку входа, проверив, имеет ли статус возврата 0 и, если это так, выход из цикла.

С Руководство по bash :

-t время ожидания

Причина чтение для тайм-аута и возврата ошибки, если полная строка ввода не будет считана в течение timeout секунд. timeout может быть десятичным числом с дробной частью после десятичной точки. Этот параметр действует, только если read читает входные данные из терминала, канала или другого специального файла; это не влияет на чтение из обычных файлов. Если timeout равно 0, read возвращает успех, если в указанном дескрипторе файла имеется ввод, иначе произойдет сбой. Состояние выхода превышает 128, если превышено время ожидания.

Здесь некоторые примеры использования.

2 голосов
/ 14 марта 2011

Обычно я не против разорвать бесконечный цикл bash простым CTRL-C. Это традиционный способ завершения tail -f, например.

0 голосов
/ 01 января 2016

Вот еще одно решение.Работает для любой нажатой клавиши, включая пробел, ввод, стрелки и т. Д.

Проверено в bash:

IFS=''
if [ -t 0 ]; then stty -echo -icanon raw time 0 min 0; fi
while [ -z "$key" ]; do
    read key
done
if [ -t 0 ]; then stty sane; fi
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...