複数の 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の回答を使用するか調べます。

答え2

生産ラインに集中できるように、CASのソリューションを編集してください。

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

awk '
    # every time theres a match, save that line into a variable
    /string1/ { str1 = $0 }
    /string2/ { str2 = $0 }
    /string3/ { str3 = $0 }
    END {
      # and only print to file after reading the whole log.
      print str1 >> "output1.log"
      print str2 >> "output2.log"
      print str3 >> "output3.log" 
}' input.log

答え3

入力ファイル

praveen
ajay
abhi
praveen
ajay
abhi
kiran
tomato

私たちの要件は、別のテキスト文字列を検索し、出力を別のテキストファイルに書き込むことです。

同じ目的を達成するために、forループとsedコマンドを使用しました。

praveen、ajay、abhiコンテンツ検索を試み、結果をcontentsearch.txtに保存しました。

スクリプト

for i in praveen ajay abhi; do sed -n "/$i/p" input.txt > $i.txt; done

以下は出力になります

praveen.txt  will contains line where praveen is present
ajay.txt will contains line where ajay is present
abhi.txt will contains where abhi is present

================================================== ============================

テスト文字列に一致するログファイルの最後の行を検索して別のファイルに出力するには、次のコマンドを使用します。

sed -n '/Contentsearch/p' input.txt | tail -1 > output.txt

関連情報