Перед читанням очистіть stdin


14

У мене є такий сценарій bash:

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

Тепер, як ви могли здогадатися, якщо користувач натискає якісь випадкові клавіші під час "трудомісткого завдання", також враховується небажаний ввід. Як я очищую stdin(або принаймні ігнорую), перш ніж видавати команду read?


1
Сам, якщо ви не пишете програми, схожі на прокляття, я вважаю, що ви хочете зробити, щоб бути вадою дизайну у вашій програмі. У UNIX / Linux є дуже корисна функція буферного введення ("наперед"), і я зазвичай використовую цю функціональність. Переходячи через вашу програму, де ви викидаєте те, що я набрав, я, швидше за все, надішлю помилку і перестану використовувати вашу програму, поки вона не буде виправлена.
Арседж

1
Деякі користувачі дратують звичку грати на фортепіано зі своєю клавіатурою, поки їх програма зайнята чимось. Я б швидше відкинув ці натискання клавіш і почав свіжий. Але ти маєш рацію, "наперед" корисний, але не завжди.
Рабін

Відповіді:


8

Я не думаю, що є спосіб очистити stdin, але (з 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

21

У 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

Це, здається, працює, лише якщо користувач натискає клавішу Enter після клавіш. Якщо користувач щойно набрав випадкові клавіші (& no enter press), цикл негайно виходить, не очищаючи буферизовані символи.
БТ

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

Я вважаю, що це не має нічого спільного з питанням.
Скотт

Але це робить! Користувач хоче, щоб весь вхід був відкинутий. Якщо забороняти введення, це робить саме так - оскільки stdin закритий, весь вхід відкидається (системою). Це елегантне рішення його проблеми. Він отримує систему зробити відмову без проблем записати цикл відкидання.
HiTechHiTouch

Це здається найнадійнішим варіантом поки що.
Стівен Ейлерт

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

4

Спираючись на відповідь Кристофягера, я додав, -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.