Kết hợp nhiều lệnh unix thành một đầu ra


9

Tôi cần tìm kiếm nhật ký thư của chúng tôi để biết địa chỉ e-mail cụ thể. Chúng tôi giữ một tệp hiện tại có tên maillog cũng như các tệp .bz2 trị giá một tuần trong cùng một thư mục. Hiện tại, tôi đang chạy các lệnh sau để tìm kiếm tệp:

grep person@domain.com maillog
bzgrep person@domain.com *.bz2

Có cách nào kết hợp các lệnh grepbzgrepthành một đầu ra không? Bằng cách đó, tôi có thể chuyển các kết quả được kết hợp thành một e-mail hoặc một tệp duy nhất.

Câu trả lời:


24

Một cách khác là

{ grep ...; bzgrep ...;} >file

&&có khó khăn là bzgrepsẽ không được chạy nếu grepthất bại.

Lưu ý không gian bắt buộc sau dấu ngoặc nhọn mở và dấu chấm phẩy sau lệnh cuối cùng. Ngoài ra, bạn có thể sử dụng cú pháp subshell (dấu ngoặc đơn thay vì dấu ngoặc nhọn), điều này không kén chọn:

(grep ...; bzgrep ...) >file

+1 cho cách tiếp cận mục đích chung tốt nhất cho vấn đề này. Shell nhóm là một tính năng thường không được sử dụng.
Phil Hollenback

2
Ý bạn là ()thay vì {}?
Ehtesh Choudhury

Trên arch linux, cái này hoạt động với ()nhưng không {}, dù là +1 vì đây là thứ tôi cần!
Chris Magnuson

11

bzgrep tự động mặc định thành grep thông thường nếu một tệp không được nén bằng bzip. Do đó, những điều sau đây là đủ:

bzgrep person@domain.com maillog *bz2 | mail -s "logs yay" someuser@blah

Tất nhiên, đây cũng là giải pháp GNU Parallel bắt buộc của tôi :

parallel -m bzgrep person@domain.com ::: maillog* *bz2 | mail -s "logs yay" someuser@blah

có thể nhanh hơn rất nhiều nếu bạn đang kiểm tra nhiều tệp.


2

Đây là một cách khác để làm điều đó (giả sử bạn đang chạy bash, có thể là bạn):

cat <(bzgrep ...) <(grep ...)

Ở đây bash đang cung cấp một cách minh bạch đầu ra của các lệnh bzgrep và grep thành cat như thể chúng là các tệp (và chúng sắp xếp dưới mui xe, chi tiết trong url ở dưới cùng).

Trong trường hợp cụ thể của bạn, tôi muốn giới thiệu giải pháp của Phil, nhưng ở trên là một mẹo hay để giữ trong túi của bạn.

Nếu bạn quan tâm, bạn có thể đọc thêm tại đây: http://www.tldp.org/LDP/abs/html/ process-sub.html


À đúng rồi, câu trả lời chính tắc cho 'làm thế nào để bạn khác với đầu ra của hai quá trình'. Một mẹo hay để biết.
Phil Hollenback

1

Tại thời điểm tôi viết bài này, cú pháp của câu trả lời được chấp nhận là sai đối với hầu hết, nếu không phải tất cả, các vỏ có nguồn gốc Bourne, bao gồm cả bash. Tôi đã đề xuất một chỉnh sửa lên đầu và chấp nhận câu trả lời để khắc phục điều đó, nhưng tôi cũng có xu hướng thêm tất cả các thông tin khác này và điều này sẽ được viết lại nhiều hơn thay vì chỉnh sửa.

Bạn có thể sử dụng các lệnh ghép:

{ grep ...; bzgrep ...; } >file

.. hoặc subshells (lưu ý dấu ngoặc đơn thay vì dấu ngoặc nhọn):

(grep ...; bzgrep ...) >file

.. để nhóm các lệnh. Cách thức con có cú pháp đẹp hơn (tha thứ hơn cho việc thiếu khoảng trắng và cho phép bạn bỏ qua dấu chấm phẩy cuối cùng), nhưng nó sẽ tạo ra một quy trình mới hoặc "giả vờ" bằng cách chạy các lệnh trong môi trường được dọn sạch. Cả hai đều có lợi thế tùy thuộc vào những gì bạn muốn làm, điều này không quan trọng ở đây, nhưng đáng để tìm kiếm nếu bạn muốn thành thạo hơn với vỏ.

Lưu ý: Bạn cũng có thể sử dụng pipelining với các thủ thuật này, vì vậy bạn có thể làm một cái gì đó như thế này:

{ grep ...; bzgrep ...; } | less

PS nếu bạn không quan tâm đến thứ tự của các trận đấu trong đầu ra kết hợp của mình, bạn có thể sử dụng một lệnh duy nhất &giữa hai lệnh, như vậy : { grep ... & bzgrep ...; }. Sau đó, hai lệnh chạy đồng thời: grepshell được khởi chạy và shell đặt nó dưới nền, sau đó shell sẽ chạy bzgrep. (Nhưng có một cảnh báo nhỏ với điều đó, với lời giải thích liên quan đến chuyển hướng tệp và bộ đệm luồng tệp có khả năng khiến một phần rất nhỏ các dòng trong tệp đầu ra bị phân tách / xáo trộn: bạn có thấy điều này phụ thuộc vào cách grep, bzgrepvà các libc stdio.hchức năng được triển khai. Trong hầu hết các triển khai, tôi tin rằng việc đặt lệnh trước khi chuyển hướng đến một tệp sẽ tránh được vấn đề, vì vậy bạn có thể làm { foo & bar; } | cat - >filenhư một cách giải quyết.)


0

Bạn có thể buộc các lệnh cùng với && sẽ cho phép bạn chạy từng lệnh.

bạn cũng có thể thêm >> textfile.txt vào cuối mỗi lệnh và để đầu ra nhấn một tệp sau đó gửi tệp đó ra.


2
Như geekizard đã đề cập, && không nên được sử dụng ở đây vì giá trị trả về của grep phụ thuộc vào việc nó có tìm thấy thứ gì đó hay không. Nếu bạn đã làm grep ... && bzgrep ..., nếu grep không có lượt truy cập, nó sẽ trả về thất bại và lệnh sẽ dừng lại. >>là một ý tưởng tốt, mặc dù, không giống như vậy >, nó sẽ thêm đầu ra vào cuối của một tệp hiện có.
DerfK

đúng tôi đã quên về điều kiện thoát ngăn chặn lệnh thứ hai.
Mike
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.