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?


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.


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

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

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


5

das hat bei mir gut funktioniert:

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

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

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

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.