Gabungkan beberapa perintah unix menjadi satu output

9

Saya perlu mencari log surat kami untuk alamat email tertentu. Kami menyimpan file saat ini bernama maillog serta file .bz2 dalam satu minggu dalam folder yang sama. Saat ini, saya menjalankan perintah berikut untuk mencari file:

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

Apakah ada cara menggabungkan grepdan bzgrepperintah menjadi satu output? Dengan begitu, saya bisa mengirim hasil gabungan ke satu email atau satu file.

Ben McCormack
sumber

Jawaban:

24

Cara lain adalah

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

&&memiliki kesulitan yang bzgreptidak akan dijalankan jika grepgagal.

Perhatikan ruang wajib setelah kurung kurawal pembukaan dan titik koma setelah perintah terakhir. Atau, Anda dapat menggunakan sintaksis subkulit (kurung alih-alih kurung kurawal), yang tidak pilih-pilih:

(grep ...; bzgrep ...) >file
geekosaurus
sumber
+1 untuk pendekatan shell tujuan umum terbaik untuk masalah ini. Pengelompokan shell adalah fitur yang umumnya kurang dimanfaatkan.
Phil Hollenback
2
Bukankah maksud Anda, ()bukan {}?
Ehtesh Choudhury
Pada arch linux ini bekerja dengan ()tetapi tidak {}, dengan cara +1 karena inilah yang saya butuhkan!
Chris Magnuson
11

bzgrep secara otomatis default ke grep reguler jika file tidak dikompresi bzip. Jadi yang berikut ini harus cukup:

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

oh juga tentu saja inilah solusi paralel GNU wajib saya juga:

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

yang bisa menjadi jauh lebih cepat jika Anda memeriksa banyak file.

Phil Hollenback
sumber
2

Berikut cara lain untuk melakukannya (dengan asumsi Anda menjalankan bash, yang mungkin Anda alami):

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

Di sini bash secara transparan memasukkan output dari perintah bzgrep dan grep ke dalam cat seolah-olah itu adalah file (dan mereka semacam berada di bawah tenda, rincian dalam url di bagian bawah).

Dalam kasus khusus Anda, saya akan merekomendasikan solusi Phil, tetapi di atas adalah trik yang baik untuk disimpan dalam tas Anda.

Jika Anda tertarik, Anda dapat membaca lebih lanjut di sini: http://www.tldp.org/LDP/abs/html/process-sub.html

Drew Bloechl
sumber
Ah ya, jawaban kanonik untuk 'bagaimana Anda membedakan hasil dari dua proses'. Trik yang bagus untuk diketahui.
Phil Hollenback
1

Pada saat saya menulis ini, sintaks jawaban yang diterima salah untuk sebagian besar, jika tidak semua, cangkang yang diturunkan dari Bourne, termasuk bash. Saya menyarankan edit ke atas dan menerima jawaban untuk memperbaikinya, tetapi saya juga cenderung menambahkan semua informasi ini, dan ini akan lebih berupa penulisan ulang daripada edit.

Anda dapat menggunakan perintah majemuk:

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

..atau subkulit (perhatikan tanda kurung alih-alih kurung kurawal):

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

..untuk mengelompokkan perintah. Cara subshell memiliki sintaksis yang lebih bagus (lebih memaafkan kurangnya ruang putih dan memungkinkan Anda untuk menghilangkan titik koma terakhir), tetapi itu baik garpu proses baru, atau "berpura-pura" dengan memiliki perintah berjalan di lingkungan yang dibersihkan. Keduanya memiliki kelebihan tergantung pada apa yang ingin Anda lakukan, yang tidak penting di sini, tetapi patut dicari jika Anda ingin lebih mahir dengan shell.

Catatan: Anda juga dapat menggunakan pipelining dengan trik-trik ini, sehingga Anda dapat melakukan sesuatu seperti ini:

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

PS jika Anda tidak peduli tentang urutan pertandingan dalam output gabungan Anda, Anda bisa menggunakan satu &di antara dua perintah, seperti: { grep ... & bzgrep ...; }. Kemudian kedua perintah berjalan secara bersamaan: yang grepdiluncurkan dan shell meletakkannya di latar belakang, maka shell akan menjalankan bzgrep. (Tapi ada peringatan kecil dengan itu, dengan penjelasan yang melibatkan pengalihan file dan buffering aliran file berpotensi menyebabkan sebagian kecil dari baris dalam file output menjadi terpecah / hancur: apakah Anda akan melihat ini tergantung pada bagaimana Anda grep, bzgrep, dan libc stdio.hfungsi diimplementasikan. Pada sebagian besar implementasi, saya percaya memipakan perintah sebelum mengalihkan ke file akan menghindari masalah, sehingga Anda bisa melakukan { foo & bar; } | cat - >filesebagai solusinya.)

mtraceur
sumber
0

Anda dapat mengikat perintah bersama dengan && yang memungkinkan Anda menjalankan setiap perintah.

Anda juga bisa menambahkan >> textfile.txt ke akhir setiap perintah dan memiliki output menekan file kemudian mengirimkan file itu keluar.

Mike
sumber
2
Seperti yang disebutkan geekosaurus, && tidak boleh digunakan di sini karena nilai pengembalian grep bergantung pada apakah ia menemukan sesuatu atau tidak. Jika Anda melakukannya grep ... && bzgrep ..., jika grep tidak memiliki hit, itu akan mengembalikan kegagalan dan perintah akan berhenti. >>adalah ide yang bagus, tidak seperti >itu, itu akan menambah output ke akhir file yang ada.
DerfK
benar saya sudah lupa tentang kondisi keluar mencegah perintah kedua.
Mike