複数の Grep 検索

複数の Grep 検索

テスト文字列に一致するログファイルの最後の行を取得し、別のログファイルに出力したいと思います。

さまざまなテキスト文字列をテストし、出力に応じてさまざまなログファイルに送信する必要があります。

私はこれを使用しています:

tail -f -n 1 input.log | grep string1 >>output1.log

その後、次のようにテストを繰り返したいと思います。

tail -f -n 1 input.log | grep string2 >>output2.log
tail -f -n 1 input.log | grep string3 >>output3.log

効率的な単一のbashスクリプトでこれをどのように達成できますか?

ベストアンサー1

grepの代わりにawkを使用してください。

awk '/string1/ { print >> "output1.log" ; fflush() }
     /string2/ { print >> "output2.log" ; fflush() }
     /string3/ { print >> "output3.log" ; fflush() }' input.log

この出力みんな行を対応するoutput.logファイルと一致させます。それはあなたの矛盾tail -fと要件を理解できないからですtail -n 1input.log現在の最後の行から始めるには、tail -f -n 1スクリプトをパイプしawkinput.logその行の終わりを削除します。例えば

tail -f -n 1 input.log | awk '...same awk script as above...'

teeまた、grepそれを行うことができますし、プロセスの交換 (しかし、かなり遅くなるでしょう):

tee >(grep --line-buffered string1 >> output1.log) \
    >(grep --line-buffered string2 >> output2.log) \
    >(grep --line-buffered string3 >> output3.log) < input.log

または

tail -f -n 1 input.log | tee .....

メモ:fflush()in -solutionawkおよびin-solution--line-bufferedオプションは、(または他の無限プロセス)の出力をまたはにパイプする場合にのみ必要です。teetail -fawktee

これがなければ、出力ファイルは出力バッファ(awkまたはgrep)がいっぱいになったときにのみ書き込まれます。ジョブがバッファに書き込まれていない出力で中断された場合(たとえば、Ctrl-Cを押す)、すべての出力は依然として失われます。バッファ。

これを使用すると、両方のソリューションがはるかに遅くなります(書き込みごとに出力をフラッシュするため)。ただし、入力ファイルが非常に大きくない場合は問題になりません。

ちなみに、これは入力の終わりに問題ではありません。この場合、awk と grep はどちらも終了する前に出力バッファを自動的にフラッシュします。

別の選択肢は、サブシェルでパイプawk(または)を実行してCtrl-Cの割り込み信号をキャプチャして無視することです。tee例えば

tail -f input.log | ( 
  trap '' INT
  awk '/string1/ { print >> "output1.log" }
       /string2/ { print >> "output2.log" }
       /string3/ { print >> "output3.log" }'
  )

tail -fCtrl-Cを押すと影響しますが(終了)、実行中のサブシェルはawkそれを無視します。 awk出力バッファをフラッシュし、tail入力が完了して終了すると終了します。

バラよりawkスクリプトからCtrl-Cをキャプチャする別の例/説明。


ログファイルに従わない場合は、tail's-fオプションを使用しないでください。

tail -n 1 | .....3つの文字列のすべての最後の項目をその出力ファイルに印刷するGuyの回答を使用するか調べます。

おすすめ記事