Okumadan önce stdin'i temizleyin


14

Aşağıdaki bash betiği var:

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

Tahmin edebileceğiniz gibi, bir kullanıcı "zaman alan görev" sırasında bazı rastgele tuşlara basarsa, istenmeyen girdi de dikkate alınır. stdinOkuma komutunu vermeden önce nasıl temizlerim (veya en azından yoksayırım)?


1
Kendim, lanet benzeri bir program yazmadıkça, programınızda bir tasarım kusuru olmak için ne yapmak istediğinizi bulurum. UNIX / Linux, arabellekleme girişinin ("yazım öncesi") çok kullanışlı özelliğine sahiptir ve genellikle bu işlevselliği kullanırım. Yazdığım şeyi attığınız programa rastlarsanız, büyük bir hata gönderir ve düzeltilene kadar programınızı kullanmayı bırakardım.
Arcege

1
Bazı kullanıcıların programları bir şey yapmakla meşgulken klavyeleriyle piyano çalma alışkanlığı vardır. Bu tuş vuruşlarını atmayı ve yeni başlamayı tercih ederim. Ama haklısınız, "önden yazma" yararlıdır, ancak her zaman değil.
rabin

Yanıtlar:


8

Stdin'i temizlemenin bir yolu olduğunu sanmıyorum ama (bash ile) girdiyi sormadan önce orada ne olduğunu okuyabilir ve atabilirsiniz

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

Bu stdin'i okur ve 1 saniyelik bir zaman aşımına sahiptir, stdin'de 10000'den fazla karakter varsa başarısız olur. Nchars parametresini ne kadar büyük yapabileceğinizi bilmiyorum.


Aslında bu hack'i bir forumda bulmuştum. Bunu yapmanın daha iyi bir yolunu bekliyordum. Görünüşe göre öyle değil.
rabin

@rabin: Eğer buraya yazmanın daha iyi bir yolunu bulursanız, birkaç senaryoda var.

Ne yazık ki bu tüm kabuklarla çalışmaz, örneğin çizgi :(
scai

21

Bash 4'te -t(zaman aşımı) değerini ayarlayabilirsiniz 0. Bu durumda, readderhal bekleyen veri olup olmadığını gösteren bir çıkış durumu ile döner:

# 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

Bu, birden fazla girdi satırını okur, eğer kullanıcı yanlışlıkla basıldığında birden çok kez girilir


5

bu benim için iyi çalıştı:

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

neden -ebu durumda?
nhed

@nhed emin değilim, belki sisteme özgü bazı sorunları atlatmak
pschichtel

4

Zaman alıcı görevi stdin kapalı bir blok içine alın:

{
     # time consuming task
} <&-

read -p "Give me some input: " input

Bunun soru ile ilgisi olmadığına inanıyorum.
Scott

Ama öyle! Kullanıcı tüm girdilerin atılmasını istiyor. Girişe izin vermemek tam olarak bunu yapar - stdin kapalı olduğundan, tüm giriş atılır (sistem tarafından). Sorununa zarif bir çözüm. Atma döngüsü yazma zahmetine girmeden sistemi atma işlemini gerçekleştirir.
HiTechHiTouch

Bu şimdiye kadarki en güvenilir seçenek gibi görünüyor.
Stephen Eilert

Mükemmel görünüyor ama benim için çalışmıyor. Bas.0 5.0 ve 4.4.19'u denedim. görev readsırasında girilen ilk satırı hala okuyacaktır # time consuming. Ayrıca, komut dosyası stdin'den sonra stdin'i okuyan komutlar içermiyorsa read, komut dosyası sonlandıktan sonra okunmamış satırlar etkileşimli terminalde yürütülür. Bunu başarıyla test eden var mı?
Socowi

4

Christophjaeger'ın cevabına -sdayanarak, girişin terminale yankılanmaması ve -nböylece yeni bir hat beklememesi için ekledim .

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

Kullanmak -niyi bir fikirdir, ancak önceki iki cevaptan daha önce bahsetmiştik. Ve bu alıştırmanın amacının , idam edilmeden önce yazılan her şeyi okumak ve atmak olduğu göz önüne alındığında read , bunun ne kadar iyi -solacağını düşündüğünüzü anlamıyorum.
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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.