こんにちは、河野です。
ログ調査の時にはgrep使いますよね!でも良くオプションを忘れてしまうので、おさらいしてみました。
ファイルの扱い
基本の文法としては、
1 |
grep オプション 条件 ファイル |
です。ファイルの指定がされない場合は標準入力を対象にしますので、
1 |
cat access.log | grep "GET / " |
という使い方をすることがあります。
ファイル名の制御
ファイルを複数指定したとき、ファイル名が先頭に出力されるのが邪魔なことが多いです。そんな時には -h オプションをつけます。
1 |
grep -h "GET / " *.log |
標準入力から受け取った場合はファイル名がありませんので、-H, --labelオプションを組み合わせて使います。
1 |
cat *.log | grep --label=log -H "GET / " |
出力内容を変更する
ファイル名の出力
マッチしたファイルが分かれば良い(ファイル名がほしい)という時には、-lオプションを使います。
1 |
grep -l "GET / " *.log |
逆に一致しないファイルが欲しいとき、-L オプションを使います。
1 |
grep -L "GET / " *.log |
ちなみに、l, L オプションは初回の一致でそのファイルの処理を停止するようになっています。賢いですね。
ファイル内での一致回数が欲しいときは、-c オプションです。ファイル名と回数のみが出力されます。
1 |
grep -c "GET / " *.log |
検索結果の出力
一致した場所に色づけするには、--color オプションです
1 |
grep --color=auto "GET / " *.log |
一致した回数を制御するには -m オプションです。
1 |
grep -m 1 "GET / " *.log |
一致した前後の行を出力するには、-A, -B, -C オプションを使います。
-A: after (一致後)
-B: before (一致前)
-C: context (一致前後)
1 2 3 |
grep -A 2 "GET / " *.log grep -B 2 "GET / " *.log grep -C 2 "GET / " *.log |
-C 2
は -A 2 -B 2
と同じ結果になります。
行数が欲しい場合には、-n オプションです。
1 |
grep -n "GET / " *.log |
パターンについて
正規表現の種類
-Gオプション(デフォルト)を使うと、基本的な正規表現を使用しますが、-E オプションを使うと拡張された正規表現が使えます。具体的に言うと、
? + { | ( )
の特殊記号がそのまま使えます。基本正規表現だと、バックスラッシュでエスケープする必要があります。
1 2 |
grep -E "GET .*\.(js|css)" *.log grep -G "GET .*\.\(js\|css\)" *.log |
この2つは同じ結果になります。正規表現を使って探すときには、エスケープが面倒なので、-E オプションを使うようにしておいた方が良いかも知れませんね。
さらに、-P オプションでPerl互換の正規表現(PCRE)が使えます。\wや\dといった表現が使えるようになるので便利です。
1 |
grep -P "HEAD \S+ HTTP" *.log |
例えばHEADのアクセスのみ抽出するとか。
また、正規表現ではなく固定文字列として扱う、-F オプションもあります。正規表現として扱わせたくない、特殊文字がある場合に使えます。
1 |
grep -F "[28/Nov" *.log |
-i オプションもあります。大文字小文字を識別しない(ignore case)ためのオプションです。
1 |
grep -i -e "get / http" *.log |
パターンのAND
AND したいときは、パイプを使って、絞り込んでいきます。オプションだけでは対応できないようですね。
1 |
grep "GET / " *.log | grep iPhone |
パターンのOR
複数の条件で OR したい時は、条件を複数記述します。その際に、-e を使わないとファイル名と扱われてしまうので、注意が必要です。普段は省略していることが多いかも知れませんが、-eの後に記述されたものがパターンとして使用されます。
1 |
grep -e "GET .*\.js" -e "GET .*\.css" *.log |
外部ファイルを使って条件を指定する方法もあります。以下のような条件を設定したファイルを用意しておきます。
1 2 3 |
$ cat regex.txt GET .*\.js GET .*\.css |
実行する際には、-f オプションを使います。
1 |
grep -f regex.txt *.log |
パターンの除外
一致した行を除きたいときには-vオプションを使います。
1 |
grep -v "GET /favicon.ico" *.log |
--recursive, -r オプション
このオプション、今回のためにmanを読んでいて知ったのですが、ディレクトリを対象として再帰的にファイルを探索するというオプションです。
1 |
grep -e "GET / " -r ./log |
という感じで使います。logディレクトリにあるファイルを再帰的に探索します。これは、
1 |
find ./log -type f | xargs grep -e "GET / " |
と同様の結果になります。
最近ようやくfind, xargsとgrepの組み合わせに慣れてきたところなのですが、grepの-rオプションがあれば、ずいぶん楽になりそうです。
また、--include, --exclude
が使えます。
特定のファイルだけ対象にしたい
1 |
grep -e "GET / " --include *.log -r ./log |
特定のファイルを除外したい
1 |
grep -e "GET / " --exclude *.log -r ./log |
これでまたログ調査が捗りますね!