ท่อทั้ง stdout และ stderr ในทุบตี?


156

ดูเหมือนว่าเวอร์ชั่นใหม่ของ bash จะมี&>โอเปอเรเตอร์ซึ่ง (ถ้าฉันเข้าใจถูกต้อง) ให้เปลี่ยนเส้นทางทั้ง stdout และ stderr ไปที่ไฟล์ (ต่อ&>>ท้ายไฟล์แทนเช่นเอเดรียนชี้แจง)

อะไรคือวิธีที่ง่ายที่สุดในการบรรลุสิ่งเดียวกัน แต่แทนที่จะส่งไปยังคำสั่งอื่น

ตัวอย่างเช่นในบรรทัดนี้:

cmd-doesnt-respect-difference-between-stdout-and-stderr | grep -i SomeError

ฉันต้องการให้ grep จับคู่กับเนื้อหาทั้งใน stdout และ stderr (มีประสิทธิภาพรวมเข้ากับสตรีมเดียว)

หมายเหตุ : คำถามนี้ถามเกี่ยวกับการวางท่อไม่ใช่การเปลี่ยนเส้นทาง - ดังนั้นจึงไม่ใช่คำถามที่ซ้ำกันซึ่งปัจจุบันถูกทำเครื่องหมายว่าซ้ำซ้อน


ดูคำตอบที่สอง ( stackoverflow.com/a/637834/1129642 ) ในคำถามที่เชื่อมโยงสำหรับวิธีที่ถูกต้องในการไพพ์ทั้ง stdout และ stderr ไม่จำเป็นต้องมีคำถามอื่น
Marki555

4
@triplee ไม่เหมือนกันใช่มั้ย ไปป์เทียบกับเปลี่ยนเส้นทางไปยังไฟล์หรือไม่
Benjamin W.

@BenjaminW มีคำตอบอย่างน้อยหนึ่งข้อที่แก้ไขทั้งสองสถานการณ์แม้ว่าจะไม่ใช่คำตอบที่ยอมรับ นี่เป็นคำถามที่พบบ่อยพอสมควรดังนั้นเราอาจจะหาสิ่งที่ซ้ำซ้อนได้ดีขึ้นหรือขอให้ผู้ดำเนินการรวมสิ่งเหล่านี้ - หรือแม้แต่ในกรณีที่แย่ที่สุดให้สร้างบัญญัติใหม่ทั้งหมดสำหรับหัวข้อนี้ หากคุณพบว่ามีล่อดีกว่าโดยทั้งหมดเสนอมัน ขอบคุณล่วงหน้า.
tripleee

12
@tripleee แก้ใช่ แต่ไม่มีคำตอบที่ใช้|&ทางลัดซึ่งฉันคิดว่าเป็นทางออกที่สะดวกที่สุดในการ "เปลี่ยนเส้นทางทั้ง stdout และ stderr ไปยังไปป์"
Benjamin W.

3
นี่ไม่ใช่คำถามที่เชื่อมโยงซ้ำและไม่ชัดเจนว่าคำตอบของ Marko ทำในสิ่งที่ฉันต้องการ นอกจากนี้ยังไม่ได้พูดถึง | & การลงคะแนนเพื่อเปิดใหม่
Martin Bonner สนับสนุน Monica

คำตอบ:


163

(โปรดทราบว่าจะต่อ&>>file ท้ายไฟล์ในขณะที่&>จะเปลี่ยนเส้นทางและเขียนทับไฟล์ที่มีอยู่ก่อนหน้านี้)

การรวมstdoutและการที่คุณจะเปลี่ยนเส้นทางหลังกับอดีตใช้stderr 2>&1นี่จะเปลี่ยนเส้นทาง stderr (file descriptor 2) ไปยัง stdout (file descriptor 1) เช่น:

$ { echo "stdout"; echo "stderr" 1>&2; } | grep -v std
stderr
$

stdoutไปที่ stdout stderrไปที่ stderr grepเห็นเฉพาะstdoutจึงstderrพิมพ์ไปที่เทอร์มินัล

ในทางกลับกัน:

$ { echo "stdout"; echo "stderr" 1>&2; } 2>&1 | grep -v std
$

หลังจากเขียนถึง stdout และ stderr แล้วให้2>&1เปลี่ยนเส้นทาง stderr กลับไปที่ stdout และgrepเห็นทั้งสองสตริงบน stdin ดังนั้นจึงกรองทั้งคู่

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับการเปลี่ยนเส้นทางที่นี่

เกี่ยวกับตัวอย่างของคุณ (POSIX):

cmd-doesnt-respect-difference-between-stdout-and-stderr 2>&1 | grep -i SomeError

หรือใช้>=bash-4:

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError

&>>ขอขอบคุณสำหรับการชี้แจงใน ฉันแก้ไขคำถามของฉันแล้ว
Andrew Ferrier

18
ฉันเพิ่มตัวอย่างของคุณลงในคำตอบของฉันในกรณีที่มันไม่ชัดเจนตามตัวอย่างที่ฉันได้รับ ในฐานะที่เป็นด้านทราบว่าคุณยังสามารถใช้ทุบตีเฉพาะแทน|& 2>&1 |
Adrian Frühwirth

13
หมายเหตุด้านข้างเกี่ยวกับทางลัดที่|&เสนอโดย @ AdrianFrühwirthสำหรับผู้อ่านในอนาคต: คุณสมบัตินี้รองรับเฉพาะbashรุ่น 4+ เท่านั้น หากคุณกำลังใช้ 3 2>&1 |หรือต่ำกว่าที่คุณจะต้องติดกับ
tomocafe

3
การเปลี่ยนเส้นทางทุบตีเป็นอย่างดีอธิบายที่นี่ @ AdrianFrühwirthทำงานได้ดีมากลิงก์วางไปได้ไกลกว่านี้ บางครั้งฉันหวังว่าเอกสาร Bash อย่างเป็นทางการนั้นดี
David Andreoletti

112

ทุบตีมีชวเลขสำหรับ2>&1 |คือ|&ท่อที่ทั้ง stdout และ stderr (ดูคู่มือ ):

cmd-doesnt-respect-difference-between-stdout-and-stderr |& grep -i SomeError

นี้เป็นที่รู้จักในทุบตี 4.0 ดูบันทึกประจำรุ่น


ขอขอบคุณที่เพิ่มสิ่งนี้เพื่อความสมบูรณ์ ฉันจะให้คำตอบอื่น ๆ ที่ถูกต้องเป็นคนจำนวนมากยังคงใช้ bash pre-4.0 แต่สิ่งนี้มีประโยชน์
Andrew Ferrier

9
ที่โดดเด่นที่สุดบางที Bash ที่จัดส่งบน macOS นั้นเก่าเกินไปที่จะรองรับสิ่งนี้
Flimm

@Flimm แต่ zsh ไม่ใช่
Trenton

1
เนื่องจาก ksh ใช้ | & สำหรับ coproc นี่จึงเป็นตัวเลือกที่ไม่ดีสำหรับชวเลขที่ไม่จำเป็น ฉันเกลียดที่จะเห็นเส้นที่มีกองซ้อนของ dups และการเปลี่ยนเส้นทางมากเท่ากับผู้ชายคนถัดไป แต่มีบางอย่างที่ต้องบอกว่าชัดเจน ... และฉันขอโทษที่ความคิดเห็นนี้ไม่ได้เพิ่มมากนัก ฉันแค่อยากจะแสดงความไม่พอใจกับคนจดชวเลขโดยไม่ต้องลงแรงเพื่อตอบคำถามที่เป็นประโยชน์จริง ๆ เพราะเป็นเรื่องดีที่ผู้คนเห็นสิ่งนี้ ฉันไม่รู้สิ่งนี้ดังนั้นขอบคุณที่ทำให้ฉันรู้
พอลฮอดจ์ส

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