2013-05-11 43 views
98

Có vẻ như các phiên bản mới hơn của bash có toán tử &>, mà (nếu tôi hiểu chính xác), chuyển hướng cả stdout và stderr sang một tệp (&>> nối vào tệp thay vì Adrian làm rõ).Piping cả stdout và stderr trong bash?

Cách đơn giản nhất để đạt được điều tương tự, nhưng thay vào đó là chuyển sang lệnh khác?

Ví dụ, trong dòng này:

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

Tôi muốn các grep để phù hợp với nội dung trên cả stdout và stderr (có hiệu quả, đã cho họ kết hợp thành một dòng).

Note: Câu hỏi này được hỏi về đường ống, không chuyển hướng - vì vậy nó không phải là một bản sao của câu hỏi đó hiện đang được đánh dấu là một bản sao của.

+0

Xem câu trả lời thứ hai (https://stackoverflow.com/a/637834/1129642) về câu hỏi được liên kết để biết cách chính xác để đưa cả hai tiêu chuẩn và stderr. Không cần câu hỏi khác. – Marki555

+3

@triplee Không phải là bản sao chính xác, phải không? Ống so với chuyển hướng đến tệp? –

+0

@BenjaminW Có ít nhất một câu trả lời ở đó giải quyết cả hai kịch bản, mặc dù nó không phải là câu trả lời được chấp nhận.Đây là một câu hỏi khá phổ biến, vì vậy chúng tôi có thể tìm thấy một bản sao tốt hơn, hoặc yêu cầu một người điều phối hợp nhất - hoặc thậm chí, trong trường hợp xấu nhất, tạo ra một quy tắc hoàn toàn mới cho chủ đề này. Nếu bạn tìm thấy một dupe tốt hơn, bởi tất cả các phương tiện đề xuất nó. Cảm ơn trước. – tripleee

Trả lời

114

(Lưu ý rằng &>>filegắn vào một tập tin trong khi &> sẽ chuyển hướng và ghi đè một file tồn tại trước đó.)

Để kết hợp stdoutstderr bạn sẽ chuyển hướng sau này để các cựu sử dụng 2>&1. Đây chuyển hướng stderr (file descriptor 2) để stdout (file descriptor 1), ví dụ .:

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

stdout đi vào thiết bị xuất chuẩn, stderr đi vào stderr. grep chỉ thấy stdout, do đó stderr bản in cho thiết bị đầu cuối.

Mặt khác:

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

Sau khi văn bản cho cả stdout và stderr, 2>&1 chuyển hướng stderr trở lại stdout và grep thấy cả hai chuỗi trên stdin, do đó lọc ra cả.

Bạn có thể đọc thêm về chuyển hướng here.

Về ví dụ của bạn (POSIX):

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

hay, sử dụng >=bash-4:

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

Cảm ơn bạn đã làm rõ về '& >>'. Tôi đã sửa chữa câu hỏi của mình. –

+14

Tôi đã thêm ví dụ của bạn vào câu trả lời của tôi, chỉ trong trường hợp nó không rõ ràng dựa trên các ví dụ đã cho của tôi. Là một lưu ý phụ, bạn cũng có thể sử dụng '| &' bash cụ thể thay vì '2> & 1 |'. –

+0

Cảm ơn bạn đã làm rõ. Câu trả lời hữu ích, cảm ơn. –

46

Bash có một cách viết tắt cho 2>&1 |, cụ thể là |&, mà ống cả stdout và stderr (xem manual):

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

Điều này đã được giới thiệu trong Bash 4.0, xem release notes.

+0

Cảm ơn bạn đã thêm điều này cho đầy đủ. Tôi sẽ giữ cho câu trả lời khác chính xác như nhiều folks vẫn còn sử dụng bash pre-4.0. Nhưng điều này rất hữu ích. –

+3

Đáng chú ý nhất có lẽ, Bash mà tàu trên macOS là quá cũ để hỗ trợ này. – Flimm

+0

@Flimm nhưng zsh không phải là – Trenton

Các vấn đề liên quan