Очистить стандартный перед чтением


14

У меня есть следующий скрипт bash:

# do some time consuming task here
read -p "Give me some input: " input

Теперь, как вы уже догадались, если пользователь нажимает некоторые случайные клавиши во время «трудоемкой задачи», нежелательный ввод также учитывается. Как очистить stdin(или, по крайней мере, проигнорировать) перед выполнением команды чтения?


1
Я сам, если вы не пишете программу, похожую на ругательства, я нахожу то, что вы хотите сделать, недостатком дизайна в вашей программе. UNIX / Linux имеет очень полезную функцию буферизации ввода («опережающий ввод»), и я обычно использую эту функцию. Перебирая вашу программу, где вы выбрасываете то, что я напечатал, я, скорее всего, отправлю сообщение об ошибке и перестану использовать вашу программу, пока она не будет исправлена.
Arcege

1
Некоторые пользователи имеют раздражающую привычку играть на пианино на клавиатуре, когда их программа занята чем-то. Я бы предпочел выбросить эти нажатия клавиш и начать все сначала. Но вы правы, «опечатка» полезна, но не всегда.
Рабин

Ответы:


8

Я не думаю, что есть способ очистить стандартный ввод, но (с помощью bash) вы можете прочитать и выбросить то, что есть, прежде чем запрашивать ввод

#do some time consuming task here
read -t 1 -n 10000 discard 
read -p "Give me some input: " input

Это читает stdin и имеет тайм-аут в 1 секунду, но не работает, если в stdin более 10000 символов. Я не знаю, насколько большой вы можете сделать параметр nchars.


Я действительно нашел этот взломать на форуме. Я ожидал найти лучший способ сделать это. Очевидно нет.
Рабин

@rabin: Если вы найдете лучший способ опубликовать здесь, у меня есть несколько сценариев.

К сожалению, это не работает со всеми оболочками, например, тире :(
scai

20

В Bash 4 вы можете установить -t(тайм-аут) на 0. В этом случае readсразу возвращается со статусом выхода, указывающим, ожидают ли данные:

# do some time consuming task here
while read -r -t 0; do read -r; done
read -p "Give me some input: " input

6
read -d '' -t 0.1 -n 10000

Это читает несколько строк ввода, если пользователь случайно нажал ввод несколько раз


5

это хорошо сработало для меня:

function clean_stdin()
{
    while read -e -t 0.1; do : ; done
}

почему -eв этом случае?
nhed

@nhed больше не уверен, может быть, чтобы обойти какую-то системную проблему
pschichtel

4

Заключите трудоемкую задачу в блок, чей stdin закрыт:

{
     # time consuming task
} <&-

read -p "Give me some input: " input

Я считаю, что это не имеет ничего общего с вопросом.
Скотт

Но это так! Пользователь хочет, чтобы все входные данные были отброшены. Недопустимый ввод делает именно это - поскольку стандартный ввод закрыт, весь ввод отбрасывается (системой). Это элегантное решение его проблемы. Он заставляет систему выполнить сброс без необходимости писать цикл сброса.
HiTechHiTouch

Это, кажется, самый надежный вариант на данный момент.
Стивен Эйлерт

Кажется идеальным, но не работает для меня. Я пробовал bash 5.0.0 и 4.4.19. readбудет по-прежнему читать первую строку, введенную во время # time consumingзадачи. Кроме того, если сценарий не содержит команд, которые читают stdin после readэтого, непрочитанные строки выполняются на интерактивном терминале после завершения сценария. Кто-нибудь успешно это проверял?
Socowi

4

Основываясь на ответе christophjaeger, я добавил, -sчтобы ввод не отражался на терминале и -nчтобы он не ожидал новой строки.

while read -r -t 0; do
    read -n 256 -r -s
done

Использование -n- хорошая идея, но два предыдущих ответа уже упоминали об этом. И учитывая, что цель этого упражнения - прочитать и отбросить все, что было напечатано до того, как read было выполнено , я не понимаю, что, по вашему мнению, -sбудет хорошего .
Скотт

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.