Xóa stdin trước khi đọc


14

Tôi có tập lệnh bash sau:

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

Bây giờ như bạn có thể đoán, nếu người dùng nhấn một số phím ngẫu nhiên trong "nhiệm vụ tiêu tốn thời gian", thì đầu vào không mong muốn cũng được tính đến. Làm cách nào để xóa stdin(hoặc ít nhất là bỏ qua nó) trước khi tôi phát lệnh đọc?


1
Chính tôi, trừ khi bạn đang viết một chương trình giống như lời nguyền, tôi tìm thấy những gì bạn muốn làm là một lỗ hổng thiết kế trong chương trình của bạn. UNIX / Linux có tính năng rất hữu ích của bộ đệm đầu vào ("loại trước") và tôi thường sử dụng chức năng này. Bắt gặp chương trình của bạn nơi bạn vứt bỏ những gì tôi đã nhập, tôi có thể sẽ gửi một lỗi và ngừng sử dụng chương trình của bạn cho đến khi nó được sửa.
Arcege

1
Một số người dùng có thói quen khó chịu khi chơi piano bằng bàn phím trong khi chương trình của họ đang bận rộn làm gì đó. Tôi thà vứt bỏ những tổ hợp phím đó và bắt đầu mới. Nhưng bạn đã đúng, "loại trước" là hữu ích, nhưng không phải lúc nào cũng vậy.
rabin

Câu trả lời:


8

Tôi không nghĩ có một cách để xóa stdin nhưng (với bash) bạn có thể đọc và loại bỏ những gì có trước khi bạn yêu cầu đầu vào

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

Điều này đọc stdin và có thời gian chờ là 1 giây, nó sẽ thất bại nếu có hơn 10000 ký tự trong stdin. Tôi không biết bạn có thể tạo ra tham số nchars lớn như thế nào.


Tôi thực sự đã tìm thấy hack này trên một diễn đàn. Tôi đã mong đợi để tìm ra một cách tốt hơn để làm điều đó. Rõ ràng là không.
rabin

@rabin: Nếu bạn tìm thấy một cách tốt hơn đăng lại ở đây tôi có nó trong một vài kịch bản.

Thật không may, điều này không hoạt động với tất cả các shell, ví dụ: dash :(
scai 7/12/13

20

Trong Bash 4, bạn có thể đặt -t(thời gian chờ) thành 0. Trong trường hợp này, readngay lập tức trả về với trạng thái thoát cho biết liệu có dữ liệu chờ hay không:

# 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

Điều này đọc nhiều dòng đầu vào, nếu người dùng vô tình nhấn enter nhiều lần


5

điều này làm việc tốt cho tôi:

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

Tại sao -etrong trường hợp này?
nhed

@nhed không chắc chắn nữa, có thể phá vỡ một số vấn đề cụ thể của hệ thống
pschichtel

4

Kèm theo nhiệm vụ tiêu tốn thời gian trong một khối có stdin bị đóng:

{
     # time consuming task
} <&-

read -p "Give me some input: " input

Tôi tin rằng điều này không liên quan gì đến câu hỏi.
Scott

Nhưng nó làm! Người dùng muốn tất cả đầu vào bị loại bỏ. Không cho phép đầu vào thực hiện chính xác điều đó - vì stdin bị đóng, tất cả đầu vào bị loại bỏ (bởi hệ thống). Đó là một giải pháp tao nhã cho vấn đề của anh ấy. Anh ta có được hệ thống để loại bỏ mà không gặp rắc rối khi viết một vòng lặp loại bỏ.
HiTechHiTouch

Đây dường như là lựa chọn đáng tin cậy nhất cho đến nay.
Stephen Eilert

Có vẻ hoàn hảo nhưng không làm việc cho tôi. Tôi đã thử bash 5.0.0 và 4.4.19. readvẫn sẽ đọc dòng đầu tiên được nhập trong # time consumingnhiệm vụ. Hơn nữa, nếu tập lệnh không chứa bất kỳ lệnh nào đọc stdin sau readđó thì các dòng chưa đọc được thực thi trên thiết bị đầu cuối tương tác sau khi tập lệnh kết thúc. Có ai đã thử nghiệm thành công điều này?
Socowi

4

Dựa trên câu trả lời của christophjaeger, tôi đã thêm vào -sđể đầu vào không bị dội lại đến thiết bị đầu cuối và -nđể nó không chờ đợi một dòng mới.

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

Sử dụng -nlà một ý tưởng tốt, nhưng hai câu trả lời trước đã đề cập đến nó. Và cho rằng quan điểm của bài tập này là đọc và loại bỏ bất cứ thứ gì được gõ trước khi read thực thi , tôi không hiểu bạn nghĩ điều gì sẽ tốt -s.
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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.