Vor dem Lesen den Standard löschen

14

Ich habe das folgende Bash-Skript:

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

Nun, wie Sie vielleicht erraten haben, wird die unerwünschte Eingabe ebenfalls berücksichtigt, wenn ein Benutzer während der "zeitaufwendigen Aufgabe" einige zufällige Tasten drückt. Wie lösche stdin(oder ignoriere) ich es, bevor ich den Lesebefehl erteile?

rabin
quelle
1
Ich selbst, es sei denn, Sie schreiben ein verfluchtes Programm, finde, was Sie tun möchten, um ein Designfehler in Ihrem Programm zu sein. UNIX / Linux verfügt über die sehr nützliche Funktion zum Puffern von Eingaben ("Type-Ahead"), und diese Funktionalität wird häufig verwendet. Wenn ich auf Ihr Programm stoße, in dem Sie das, was ich eingegeben habe, wegwerfen, würde ich wahrscheinlich einen Fehler melden und die Verwendung Ihres Programms einstellen, bis es behoben ist.
Arcege
1
Einige Benutzer haben die lästige Angewohnheit, mit ihrer Tastatur Klavier zu spielen, während ihr Programm beschäftigt ist, etwas zu tun. Ich würde diese Tastenanschläge lieber wegwerfen und neu anfangen. Aber du hast recht, das "Vorausschreiben" ist nützlich, aber nicht immer.
Rabin

Antworten:

8

Ich glaube nicht, dass es eine Möglichkeit gibt, stdin zu löschen, aber (mit bash) können Sie lesen und verwerfen, was da ist, bevor Sie nach der Eingabe fragen

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

Dies liest stdin und hat eine Zeitüberschreitung von 1 Sekunde. Es schlägt jedoch fehl, wenn stdin mehr als 10000 Zeichen enthält. Ich weiß nicht, wie groß Sie den Parameter nchars machen können.


quelle
Ich hatte diesen Hack tatsächlich in einem Forum gefunden. Ich hatte erwartet, einen besseren Weg zu finden. Scheinbar nicht.
Rabin
@rabin: Wenn du hier einen besseren Weg findest, poste ich ihn in ein paar Skripten.
Leider funktioniert das nicht mit allen Shells, zB dash :(
scai
20

In Bash 4 können Sie -t(Timeout) auf einstellen 0. In diesem Fall wird readsofort mit einem Beendigungsstatus zurückgegeben, der angibt, ob Daten warten oder nicht:

# do some time consuming task here
while read -r -t 0; do read -r; done
read -p "Give me some input: " input
christophjaeger
quelle
6
read -d '' -t 0.1 -n 10000

Hiermit werden mehrere Eingabezeilen gelesen, wenn der Benutzer versehentlich mehrmals die Eingabetaste gedrückt hat

Ram Natarajan
quelle
5

das hat bei mir gut funktioniert:

function clean_stdin()
{
    while read -e -t 0.1; do : ; done
}
pschichtel
quelle
warum -ein diesem Fall?
nhed
@nhed nicht mehr sicher, vielleicht ein systemspezifisches Problem zu umgehen
Pschichtel
4

Fügen Sie die zeitaufwändige Aufgabe in einen Block ein, dessen stdin geschlossen ist:

{
     # time consuming task
} <&-

read -p "Give me some input: " input
artistoex
quelle
Ich glaube, das hat nichts mit der Frage zu tun.
Scott
Aber es tut! Der Benutzer möchte, dass alle Eingaben verworfen werden. Keine Eingabe erlaubt genau das - da stdin geschlossen ist, werden alle Eingaben (vom System) verworfen. Es ist eine elegante Lösung für sein Problem. Er veranlasst das System, den Abwurf durchzuführen, ohne eine Abwurfschleife schreiben zu müssen.
HiTechHiTouch
Dies scheint die bisher zuverlässigste Option zu sein.
Stephen Eilert
Scheint perfekt, funktioniert aber bei mir nicht. Ich habe Bash 5.0.0 und 4.4.19 ausprobiert. readliest immer noch die erste Zeile, die während der # time consumingAufgabe eingegeben wurde . Wenn das Skript keine Befehle enthält, die stdin nach readdem lesen, werden die ungelesenen Zeilen auf dem interaktiven Terminal ausgeführt, nachdem das Skript beendet wurde. Hat jemand dies erfolgreich getestet?
Socowi
4

Aufbauend auf der Antwort von christophjaeger habe ich hinzugefügt -s, dass die Eingabe nicht in das Terminal zurückgesendet wird und -nnicht auf eine neue Zeile wartet.

while read -r -t 0; do
    read -n 256 -r -s
done
Peter Sutton
quelle
Verwenden -nist eine gute Idee, aber zwei frühere Antworten haben es bereits erwähnt. Und da der Sinn dieser Übung darin besteht, alles zu lesen und zu verwerfen, was vor der read Ausführung eingegeben wurde , verstehe ich nicht, was Ihrer Meinung nach das -sbewirken wird.
Scott
2
function clear_stdin()
(
    old_tty_settings=`stty -g`
    stty -icanon min 0 time 0

    while read none; do :; done 

    stty "$old_tty_settings"
)

clear_stdin
Илья Антипов
quelle