ฉันไม่ได้ตระหนักถึงรางวัลจนกระทั่งทุกวันนี้เมื่อมือใหม่บางคนพยายามตรึง UUOC ไว้กับฉันเพื่อรับคำตอบข้อใดข้อหนึ่งของฉัน cat file.txt | grep foo | cut ... | cut ...
มันเป็น ฉันให้ชิ้นส่วนของความคิดของฉันและหลังจากทำเช่นนั้นไปเยี่ยมลิงค์ที่เขาให้ฉันหมายถึงต้นกำเนิดของรางวัลและการปฏิบัติของการทำเช่นนั้น การค้นหาเพิ่มเติมทำให้ฉันมีคำถามนี้ ค่อนข้างน่าเสียดายที่แม้จะมีการพิจารณาอย่างมีสติไม่มีคำตอบรวมถึงเหตุผลของฉัน
ฉันไม่ได้ตั้งใจจะป้องกันเมื่อให้ความรู้แก่เขา ในทุก ๆ ปีในวัยเด็กของฉันฉันจะได้เขียนคำสั่งเป็นgrep foo file.txt | cut ... | cut ...
เพราะเมื่อใดก็ตามที่คุณทำบ่อยครั้งgrep
ที่คุณได้เรียนรู้การจัดวางของอาร์กิวเมนต์ไฟล์และมันก็รู้ว่าพร้อมที่แรกคือรูปแบบและคนต่อมาเป็นชื่อไฟล์
มันเป็นตัวเลือกที่มีสติเมื่อฉันตอบคำถามด้วยcat
คำนำหน้าบางส่วนเนื่องจากเหตุผลของ "รสนิยมที่ดี" (ในคำพูดของ Linus Torvalds) แต่ส่วนใหญ่สำหรับเหตุผลที่น่าสนใจของฟังก์ชั่น
เหตุผลหลังสำคัญกว่าดังนั้นฉันจะเอามันออกก่อน เมื่อฉันเสนอไปป์ไลน์เป็นวิธีแก้ปัญหาฉันคาดว่าจะสามารถใช้ซ้ำได้ มีโอกาสมากที่จะเพิ่มท่อส่งเมื่อสิ้นสุดหรือต่อท่อไปอีกท่อหนึ่ง ในกรณีที่มีการโต้แย้งไฟล์ไปยังสกรู grep ขึ้นสามารถนำมาใช้และค่อนข้างเป็นไปได้ทำเช่นนั้นอย่างเงียบ ๆโดยไม่มีข้อความข้อผิดพลาดถ้าอาร์กิวเมนต์ไฟล์ที่มีอยู่ I. e. grep foo xyz | grep bar xyz | wc
จะทำให้คุณมีวิธีการหลายเส้นในxyz
มีbar
ในขณะที่คุณจะคาดหวังว่าจำนวนของสายที่มีทั้งในและfoo
bar
ต้องเปลี่ยนอาร์กิวเมนต์เป็นคำสั่งในไปป์ไลน์ก่อนที่จะใช้มันมีแนวโน้มที่จะเกิดข้อผิดพลาด เพิ่มความเป็นไปได้ของความล้มเหลวเงียบและกลายเป็นวิธีปฏิบัติที่ร้ายกาจโดยเฉพาะ
เหตุผลก่อนหน้านี้ไม่สำคัญเช่นกันเพราะ "รสนิยมดี" เป็นเพียงเหตุผลที่เป็นสัญชาตญาณที่เข้าใจง่ายสำหรับสิ่งต่าง ๆ เช่นความล้มเหลวเงียบ ๆ ที่คุณไม่สามารถคิดได้ในขณะที่บางคนที่ต้องการการศึกษาพูดว่า "แต่ไม่ใช่ แมวตัวนั้นไร้ประโยชน์ "
อย่างไรก็ตามฉันจะพยายามทำให้เหตุผล "รสชาติดี" ในอดีตที่ฉันกล่าวถึงด้วย เหตุผลนั้นเกี่ยวข้องกับการออกแบบมุมฉากของ Unix grep
ไม่ได้cut
และไม่ได้ls
grep
ดังนั้นอย่างน้อยที่สุดก็grep foo file1 file2 file3
ขัดกับจิตวิญญาณการออกแบบ cat file1 file2 file3 | grep foo
วิธีทำมุมฉากของมันคือ ตอนนี้grep foo file1
เป็นเพียงกรณีพิเศษของgrep foo file1 file2 file3
และถ้าคุณไม่ปฏิบัติต่อมันเหมือนกันคุณอย่างน้อยก็ใช้วงจรนาฬิกาสมองที่พยายามหลีกเลี่ยงรางวัลแมวที่ไร้ประโยชน์
นั่นนำเราไปสู่การโต้แย้งที่grep foo file1 file2 file3
เชื่อมโยงกันและcat
เชื่อมโยงกันดังนั้นจึงเหมาะสมcat file1 file2 file3
แต่เพราะcat
ไม่ต่อเนื่องกันcat file1 | grep foo
ดังนั้นเราจึงละเมิดวิญญาณของทั้งcat
Unix และยิ่งใหญ่ ถ้าเป็นเช่นนั้นแล้วยูนิกซ์จะต้องใช้คำสั่งที่แตกต่างกันในการอ่านเอาต์พุตของไฟล์หนึ่งไฟล์และถ่มน้ำลายลงไปที่ stdout (ไม่ใช่การแบ่งหน้ามัน ดังนั้นคุณจะมีสถานการณ์ที่คุณพูดcat file1 file2
หรือคุณพูดdog file1
และอย่าลืมที่จะหลีกcat file1
เลี่ยงการได้รับรางวัลอย่างเป็นเรื่องเป็นราวขณะเดียวกันก็หลีกเลี่ยงdog file1 file2
เนื่องจากหวังว่าการออกแบบของdog
จะทำให้เกิดข้อผิดพลาดหากระบุไฟล์หลายไฟล์
หวังว่า ณ จุดนี้คุณจะเห็นอกเห็นใจกับนักออกแบบ Unix ที่ไม่รวมคำสั่งแยกเพื่อแยกไฟล์ออกเป็น stdout ในขณะเดียวกันก็ตั้งชื่อcat
ให้เรียงต่อกันแทนที่จะให้ชื่ออื่น <edit>
มีสุนัขดังกล่าวโชคร้าย<
ผู้ประกอบการ มันเป็นเรื่องโชคร้ายที่วางไว้ที่ส่วนท้ายของท่อเพื่อป้องกันการประกอบง่าย ไม่มีวิธีทำความสะอาดทาง syntactically หรือสกอร์เพื่อวางไว้ที่จุดเริ่มต้น มันเป็นเรื่องที่โชคร้ายที่ไม่ได้อยู่ในเกณฑ์ทั่วไปดังนั้นคุณจึงเริ่มต้นกับสุนัข แต่เพียงเพิ่มชื่อไฟล์อื่นถ้าคุณต้องการให้มันถูกประมวลผลหลังจากที่ก่อนหน้านี้ ( >
ในทางกลับกันก็ไม่ได้แย่ไปกว่าครึ่งแล้วมันมีตำแหน่งที่เกือบสมบูรณ์แบบในตอนท้ายโดยทั่วไปแล้วมันไม่ได้เป็นส่วนที่นำกลับมาใช้ใหม่ได้ของไปป์ไลน์ดังนั้นจึงเป็นสัญลักษณ์ที่โดดเด่น)</edit>
คำถามต่อไปคือเหตุผลที่จำเป็นต้องมีคำสั่งที่คายไฟล์หรือทำการต่อไฟล์หลายไฟล์เข้ากับ stdout โดยไม่ต้องดำเนินการใด ๆ เพิ่มเติม? เหตุผลหนึ่งคือการหลีกเลี่ยงคำสั่ง Unix ทุกคำสั่งที่ทำงานกับอินพุตมาตรฐานเพื่อทราบวิธีแยกอาร์กิวเมนต์ไฟล์บรรทัดคำสั่งอย่างน้อยหนึ่งอาร์กิวเมนต์และใช้เป็นอินพุตหากมีอยู่ เหตุผลที่สองคือการหลีกเลี่ยงผู้ใช้ต้องจำ: (a) ที่ขัดแย้งชื่อไฟล์ไป; และ (b) หลีกเลี่ยงข้อบกพร่องไปป์ไลน์แบบเงียบตามที่กล่าวไว้ข้างต้น
นั่นทำให้เรารู้ว่าทำไมถึงgrep
มีเหตุผลพิเศษ เหตุผลคือการอนุญาตให้ผู้ใช้คล่องแคล่วสำหรับคำสั่งที่ใช้บ่อยและแบบสแตนด์อโลน (แทนที่จะเป็นไพพ์ไลน์) มันเป็นการประนีประนอมเล็กน้อยของ orthogonality สำหรับกำไรที่สำคัญในการใช้งาน คำสั่งไม่ทั้งหมดควรได้รับการออกแบบด้วยวิธีนี้และคำสั่งที่ไม่ได้ใช้บ่อยควรหลีกเลี่ยงตรรกะเพิ่มเติมของอาร์กิวเมนต์ไฟล์อย่างสมบูรณ์ (จำไว้ว่าตรรกะพิเศษนำไปสู่ความเปราะบางที่ไม่จำเป็น grep
ยกเว้นเป็นข้อโต้แย้งที่จะอนุญาตให้ไฟล์เช่นในกรณีของ (โดยวิธีการทราบที่ls
มีเหตุผลที่แตกต่างกันโดยสิ้นเชิงที่จะไม่เพียง แต่ยอมรับ แต่ค่อนข้างต้องใช้อาร์กิวเมนต์ไฟล์)
ในที่สุดสิ่งที่สามารถทำได้ดีกว่าคือถ้าคำสั่งพิเศษเช่นgrep
(แต่ไม่จำเป็นls
) จะสร้างข้อผิดพลาดหากอินพุตมาตรฐานพร้อมใช้งาน นี่คือเหตุผลเพราะคำสั่งรวมถึงตรรกะที่ละเมิดจิตวิญญาณของมุมมองของ Unix ยิ่งใหญ่เพื่อความสะดวกของผู้ใช้ เพื่อความสะดวกของผู้ใช้เพิ่มเติมเช่นเพื่อป้องกันความทุกข์ที่เกิดจากความล้มเหลวเงียบคำสั่งดังกล่าวไม่ควรลังเลที่จะละเมิดการละเมิดของตัวเองโดยแจ้งเตือนผู้ใช้หากมีความเป็นไปได้ของความล้มเหลวเงียบ