tail -fのときにgrep一致を1つだけ印刷する方法は?

tail -fのときにgrep一致を1つだけ印刷する方法は?

アクティビティログを読み、特別な電話に応答しようとしています。

$ tail -f example.log | egrep 'pattern1|pattern2|pattern3|pattern4|pattern5'

しかし、いくつかのパターンは開発プロセスのためにほとんど印刷されず、他のパターンは非常に連続的に印刷されています。

egrepパターンごとに1つの要求のみを印刷して正しく機能するかどうかを簡単に確認するには?

答え1

次のことができます。

tail -f example.log | awk '
  BEGIN {
    n = split("pattern1,pattern2,pattern3,pattern4,pattern5", pats, /,/)
  }
  {
    found=0
    for (i in pats) if ($0 ~ pats[i]) {
      found=1
      delete pats[i]
      n--
    }
  }
  found {print; if (!n) exit}'

awkすべてのモードが表示されると終了しますが、次に何かが記録されたときにのみ終了します(tailSIGPIPE)。

あるいは、行が複数のパターンと一致しない可能性があり、すべてのパターンを見つけた後に終了することに気が付かない場合は、短くなりますが効率が低下します。

awk '/pattern1/&&!a++ || /pattern2/&&!b++ || /pattern3/&&!c++ || \
     /pattern4/&&!d++ || /pattern5/&&!e++'

zshGNUを使用するとgrep

(trap '' PIPE;tail -f example.log > >(grep -m1 pattern1) \
                                  > >(grep -m1 pattern2) \
                                  > >(grep -m1 pattern3) \
                                  > >(grep -m1 pattern4) \
                                  > >(grep -m1 pattern5))

ただし、複数のパターンに一致する行は複数回印刷されることに注意してください。

答え2

-o後で一致する部分だけを印刷すると思います。その後、次のことができます。

cat example.log | egrep -o 'pat1|pat2|pat3|pat4|pat5' | sort | uniq

出力にパターンが含まれていると、少なくとも1つの行がパターンと一致するためです。出力に5つのパターンがすべて含まれている場合、各パターンは少なくとも1行に一致します。

他の文字と一致したり、他の長さと一致したりする正規表現では機能しません。

答え3

別のアプローチは、次のように、前のパターンと一致する各パターンの行を独自の行に出力することです。

#! /bin/sh -
tput rmam # no line wrap for terminals that can do it
awk -v u="$(tput cuu1)" -v el="$(tput el)" '
  BEGIN {
    for (n = 0; n < ARGC; n++) pat[n] = ARGV[n]
    ARGC=0
  }
  {
    pre = ""; post = el "\r" u
    for (i = 1; i < n; i++) {
      if ($0 ~ pat[i]) print pre $0 post
      pre = pre "\n"
      post = post u
    }
  }
  END{printf "%s", pre}' "$@"
tput smam

と呼ばれる:

tail -f example.log | that-script pattern1 pattern2...

例:

ここに画像の説明を入力してください。

関連情報