複数のUNIXコマンドを1つの出力に結合する


9

メールログで特定のメールアドレスを検索する必要があります。maillogという名前の現在のファイルと1週間分の.bz2ファイルを同じフォルダーに保存します。現在、次のコマンドを実行してファイルを検索しています。

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

コマンドgrepbzgrepコマンドを1つの出力に組み合わせる方法はありますか?そうすれば、結合した結果を単一の電子メールまたは単一のファイルにパイプすることができます。

回答:


24

別の方法は

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

&&が失敗bzgrepすると実行されないという難しさがありますgrep

開始中括弧の後の必須スペースと最後のコマンドの後のセミコロンに注意してください。別の方法として、うるさくないサブシェル構文(中括弧の代わりに括弧)を使用することもできます。

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

この問題に対する最良の汎用シェルアプローチの場合は+1。シェルのグループ化は、一般的に十分に活用されていない機能です。
Phil Hollenback 2011年

2
()代わりにという意味{}ですか?
Ehtesh Choudhury

アーチLinuxではこれはうまくいきました()が、うまく{}いきませんでした。これは私が必要なものなので+1
Chris Magnuson、2015

11

ファイルがbzip圧縮されていない場合、bzgrepは自動的にデフォルトで通常のgrepになります。したがって、以下で十分です。

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

もちろん、ここにも私の必須のGNU Parallelソリューションがあります。

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

多くのファイルをチェックしている場合、これははるかに速くなる可能性があります。


2

これを行う別の方法を次に示します(おそらくbashを実行していると想定しています)。

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

ここで、bashはbzgrepコマンドとgrepコマンドの出力をファイルであるかのように透過的にcatにフィードしています(そして、それらは一種の内部にあり、詳細は下部のURLにあります)。

あなたの特定のケースでは私はフィルの解決策をお勧めしますが、上記はあなたのバッグに保管するのに良いトリックです。

興味がある場合は、こちらをご覧ください。http//www.tldp.org/LDP/abs/html/process-sub.html


ああ、はい、「2つのプロセスの出力をどのように比較するか」の標準的な答えです。知っておくと良いトリックです。
Phil Hollenback 2011年

1

私がこれを書いている時点では、受け入れられた回答の構文は、すべてではないにしても、ほとんどのBourne派生シェル(これはを含む)に対して間違っていましたbash。私は上部に編集を提案し、それを修正するための回答を受け入れましたが、私はまた、他のすべての情報を追加する傾向があり、これは編集ではなく書き換えのほうが多かったでしょう。

複合コマンドを使用できます。

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

..またはサブシェル(中括弧ではなく括弧に注意):

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

..コマンドをグループ化します。サブシェルの方法は構文が優れています(空白の欠如を許容し、最後のセミコロンを省略できます)が、新しいプロセスをフォークするか、クリーンアップされた環境でコマンドを実行することによって「ふり」をします。どちらも、何をしたいかに応じて利点がありますが、ここでは重要ではありませんが、シェルについてさらに熟練したい場合は調べる価値があります。

注:これらのトリックでパイプラインを使用することもできるため、次のようなことができます。

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

PS結合した出力での一致の順序を気にしない場合は&、次のように2つのコマンドの間に単一を使用できます{ grep ... & bzgrep ...; }。次に、2つのコマンドが同時に実行されます。grepは起動され、シェルはそれをバックグラウンドに配置し、シェルはを実行しbzgrepます。(ただし、ファイルのリダイレクトとファイルストリームのバッファリングに関連する説明により、出力ファイルの行のごく一部が分割/分解される可能性があります。これが表示されるかどうかはgrepbzgrep、およびlibc stdio.h関数が実装されています。ほとんどの実装では、ファイルにリダイレクトする前にコマンドをパイプ処理することで問題が回避されるため、{ foo & bar; } | cat - >file回避策として実行できます。)


0

コマンドを&&で結合すると、各コマンドを実行できます。

また、各コマンドの最後に>> textfile.txtを追加して、出力をファイルにヒットさせ、そのファイルをメールで送信することもできます。


2
geekosaurが述べたように、grepの戻り値は何かが見つかったかどうかに依存するため、ここでは&&を使用しないでください。実行したgrep ... && bzgrep ...場合、grepにヒットがなければ、失敗を返し、コマンドが停止します。 >>ただし、とは異なり>、既存のファイルの最後に出力が追加されます。
DerfK、2011年

右の2番目のコマンドを防ぐ終了条件について忘れていました。
マイク
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.