このエントリーをはてなブックマークに追加

ログなどの大量の文字列からパターンに一致する文字列を抜き出す。

行を抜き出すだけであればgrepで十分だが、該当箇所だけ抜き出す場合、sedを思い浮かべることが多いがsedはそれなりにコマンドが長く複雑になったりと構文に頭を悩ませることも多い。しかし、比較的簡単な要件であればgrepのoオプションでも可能な場合が多い。コマンドも短く覚えやすいので、知っておくと助かるはず。

通常のgrepは、ログなどの大量のテキストファイルの中から、該当する文字列が存在する行を抜き出すといった用途に使われる。あくまで”行”を抜き出す。

それに対して、grepで「o(オー)」オプション を指定するとパターン文字列に該当した行の該当した文字列を抜き出す。

例えば、

$ echo "java apache tomcat mysql syslog" | grep -o tom
tom   <= 該当した文字列のみが抜き出された。

もっと具体的な用途としては、以下のようにlogがあったとします。

$ cat something.log
2017-12-31 21:05:21 level=info log message of some system to investigate from ip=192.168.0.1
2017-12-31 22:05:21 level=alert log message of some system to investigate ip=192.168.0.1
2017-12-31 23:05:21 level=warn log message of some system to investigate ip=192.168.0.5
2018-01-01 00:05:21 level=critical log message of some system to investigate ip=192.168.0.1
2018-01-01 01:05:21 level=info log message of some system to investigate ip=192.168.0.12
2018-01-01 02:05:21 level=info log message of some system to investigate ip=192.168.0.5
....

まずは、どんなIPアドレスのログが多いのか調べたくなるものです。 ログの中のアクセス元IPアドレスを全て抽出するというお題はログ分析の場面で頻出する問題です。 こんな問題も以下のコマンドで対応ができます。

$ grep -o ip=[0-9]*\.[0-9]*\.[0-9]*\.[0-9]* something.log
ip=192.168.0.1
ip=192.168.0.1
ip=192.168.0.5
ip=192.168.0.1
ip=192.168.0.12
ip=192.168.0.5
....

パターンとして指定された「ip=[0-9].[0-9].[0-9].[0-9]」の部分を抜き出すので、「ip=」というゴミ(不要なプレフィックス)がついてしまいますが、トラブルの現場などで、ログ分析する分には十分な出力だと思います。もちろんさらにgrepやsedを用いて出力をきれいにすることは簡単にできます。 さらに、ログの中に出現するIPアドレスの出現頻度を求めるというのもよくあるニーズです。 各IPアドレスのまで求めてみましょう。

$ grep -o ip=[0-9]*\.[0-9]*\.[0-9]*\.[0-9]* something.log | sort | uniq -c
    100 ip=192.168.0.1
     18 ip=192.168.0.5
      3 ip=192.168.0.12
      ......

上記の出力はあくまでイメージですが、ログの中に192.168.0.1が100回、192.168.0.5が18回、192.168.0.12が3回出現したといったようなことがわかります。




記事一覧へ