Перед читанням очистіть 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.