ล้าง stdin ก่อนอ่าน


14

ฉันมีสคริปต์ทุบตีต่อไปนี้:

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

ในขณะที่คุณอาจเดาได้ว่าหากผู้ใช้กดปุ่มสุ่มบางอย่างระหว่าง "งานที่ต้องใช้เวลามาก" ข้อมูลที่ไม่ต้องการจะถูกนำมาพิจารณาด้วยเช่นกัน ฉันจะล้างstdin(หรืออย่างน้อยไม่สนใจมัน) ก่อนที่ฉันจะออกคำสั่งอ่านได้อย่างไร


1
ตัวฉันเองเว้นแต่ว่าคุณกำลังเขียนโปรแกรมที่คล้ายคำสาปฉันจะพบสิ่งที่คุณต้องการจะทำเพื่อเป็นข้อบกพร่องในการออกแบบในโปรแกรมของคุณ UNIX / Linux มีคุณสมบัติที่มีประโยชน์มากในการบัฟเฟอร์อินพุต ("พิมพ์ล่วงหน้า") และฉันมักใช้ประโยชน์จากฟังก์ชั่นนี้ เจอโปรแกรมที่คุณทิ้งสิ่งที่ฉันพิมพ์ฉันจะส่งบั๊กและหยุดใช้โปรแกรมของคุณจนกว่าจะได้รับการแก้ไข
Arcege

1
ผู้ใช้บางคนมีนิสัยที่น่ารำคาญในการเล่นเปียโนด้วยแป้นพิมพ์ในขณะที่โปรแกรมกำลังทำอะไรอยู่ ฉันอยากจะทิ้งการกดแป้นและเริ่มต้นใหม่ แต่คุณพูดถูก "การพิมพ์ล่วงหน้า" นั้นมีประโยชน์ แต่ไม่เสมอไป
rabin

คำตอบ:


8

ฉันไม่คิดว่าจะมีวิธีล้าง stdin แต่ (ด้วย bash) คุณสามารถอ่านและทิ้งสิ่งที่มีอยู่ก่อนที่คุณจะขออินพุต

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

สิ่งนี้อ่าน stdin และมีการหมดเวลา 1 วินาที แต่ล้มเหลวแม้ว่าจะมีมากกว่า 10,000 chars ใน stdin ฉันไม่รู้ว่าคุณสามารถสร้างพารามิเตอร์ nchars ได้ใหญ่แค่ไหน


ที่จริงฉันเจอแฮ็คนี้ในฟอรัม ฉันคาดหวังว่าจะหาวิธีที่ดีกว่าในการทำมัน ชัดเจนว่าไม่.
rabin

@rabin: หากคุณพบวิธีที่ดีกว่าโพสต์กลับมาที่นี่ฉันมีมันในไม่กี่สคริปต์

น่าเสียดายที่มันใช้ไม่ได้กับกระสุนทุกตัวเช่นdash :(
scai

20

ในทุบตี 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

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

สิ่งนี้จะอ่านอินพุตหลายบรรทัดหากผู้ใช้กดโดยไม่ตั้งใจให้ป้อนหลายครั้ง


5

นี้ทำงานได้ดีสำหรับฉัน:

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

ทำไม-eในกรณีนี้
nhed

@ ไม่มีใครแน่ใจอีกต่อไปอาจจะหลีกเลี่ยงปัญหาเฉพาะระบบบางอย่าง
pschichtel

4

ล้อมรอบภารกิจที่ต้องใช้เวลาในบล็อกที่ stdin ถูกปิด:

{
     # time consuming task
} <&-

read -p "Give me some input: " input

ฉันเชื่อว่าสิ่งนี้ไม่เกี่ยวข้องกับคำถาม
สกอตต์

แต่มัน! ผู้ใช้ต้องการอินพุตทั้งหมดที่ถูกละทิ้ง ไม่อนุญาตให้อินพุตทำเช่นนั้น - ตั้งแต่ stdin ถูกปิดอินพุตทั้งหมดจะถูกยกเลิก (โดยระบบ) มันเป็นทางออกที่ยอดเยี่ยมสำหรับปัญหาของเขา เขาได้รับระบบที่จะทำทิ้งโดยไม่มีปัญหาในการเขียนวนทิ้ง
HiTechHiTouch

นี่เป็นตัวเลือกที่น่าเชื่อถือที่สุดจนถึงขณะนี้
Stephen Eilert

ดูเหมือนจะสมบูรณ์แบบ แต่ไม่ได้ผลสำหรับฉัน ฉันพยายามทุบตี 5.0.0 และ 4.4.19 readจะยังอ่านบรรทัดแรกที่ป้อนระหว่าง# time consumingงาน นอกจากนี้หากสคริปต์ไม่มีคำสั่งใด ๆ ที่อ่าน stdin หลังจากreadนั้นบรรทัดที่ยังไม่ได้อ่านจะถูกดำเนินการบนเทอร์มินัลแบบโต้ตอบหลังจากสคริปต์สิ้นสุดลง ทุกคนประสบความสำเร็จในการทดสอบนี้หรือไม่?
Socowi

4

จากคำตอบของ Christophjaeger ฉันได้เพิ่ม-sเพื่อให้อินพุตไม่ได้ถูกสะท้อนไปยังเทอร์มินัลและ-nเพื่อไม่ให้รอขึ้นบรรทัดใหม่

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

การใช้-nเป็นความคิดที่ดี แต่คำตอบก่อนหน้านี้สองข้อได้กล่าวถึงแล้ว และเนื่องจากจุดประสงค์ของแบบฝึกหัดนี้คือการอ่านและทิ้งสิ่งใดก็ตามที่พิมพ์ก่อนที่จะ read ถูกประหารชีวิตฉันไม่เข้าใจว่าคุณคิดว่า-sจะทำอะไรดี
สกอตต์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.