257
276

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

たった6個のsedを通せば、Apacheログは驚くほど扱いやすくなる

Last updated at Posted at 2014-04-17

Q. awk '{print $9}'とかでUser-Agent丸ごと取り出したい

とか思ったことない? Apacheのログ解析で。でもできないじゃない。例えば

combined形式ログ
192.168.0.1 - - [17/Apr/2014:11:22:33 +0900] "GET /index.html HTTP/1.1" 200 43206 "https://www.google.co.jp/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36"

なんかのログで"mozilla/5.0 (Windows NT 6.1 …… Safari/537.36"の部分が欲しいなーと思って、AWKで取ろうとしても

こーなってしまう
$ awk '{print $12}' httpd-access.log
"Mozilla/5.0
$ 

なーんてふうに、最初のスペースまでで切れてしまって全然使い物にならない。さて、何とかならないものか。

A. 6個のsedコマンドにパイプで通せばできるよ

でも、そこは我らがUNIX。シェルスクリプトとパイプと標準コマンドさえあればお手のもの。sedコマンド6個通すだけでできるようになるのさ。

次のシェルスクリプトを書いてこいつに流し込むだけ。
(2014/05/05) おい、動かねーじゃねーか!という指摘を受けて修正しました。m(_ _;)m

apalognorm.sh(Apachログを整形するシェルスクリプト)
#! /bin/sh

# ----- ちょいと下ごしらえ -----
RS=$(printf '\036')             # 元々の改行位置にマークするための記号定義
LF=$(printf '\\\n_');LF=${LF%_} # sedで改行コードを挿れるための定義

# ----- 本番 -----
sed 's/^\(.*\)$/\1'"$RS"'/'                |
sed 's/"\([^"]*\)"/'"$LF"'"\1"'"$LF"'/g'   |
sed 's/\[\([^]]*\)\]/'"$LF"'[\1]'"$LF"'/g' |
sed '/^["[]/s/[[:blank:]]/_/g'             | # ここに空白の代替文字
sed 'N;$s/\n//g'                           |
sed 's/'"$RS"'/'"$LF"'/g'

試しに実行してみると、

ほらこのとおり
$ cat httpd-access.log | apalognorm.sh
192.168.0.1 - - [17/Apr/2014:11:22:33_+0900] "GET_/index.html_HTTP/1.1" 200 43206 "https://www.google.co.jp/" "Mozilla/5.0_(Windows_NT_6.1;_WOW64)_AppleWebKit/537.36_(KHTML,_like_Gecko)_Chrome/34.0.1847.116_Safari/537.36"
$ 

日時列(4列目)、HTTPリクエストパラメーター列(5列目)、User-Agent列(9列目)に含まれているスペースが全て_に置換されている。もちろん、列を区切っているスペースはそのままで。

もし、_が気に食わないのであれば*でも+でも、好きな文字列(2文字以上でもいい)を4番目のsedの後半部分に書けばいいだけ。

6つのsedは何をやってるのか?

sed 1号

(加工の都合により、途中で一時的に改行を挿むので)元の改行を別の文字(0x1e)で退避させておく。

sed 2号

ダブルクォーテーションで囲まれている区間"~"があったら、その前後に改行を挿み、その区間を単独の行にする。

sed 3号

ブラケットで囲まれいる区間[~]も同様に、前後に改行を挿んで、この区間を単独の行にする。

sed 4号

ダブルクォーテーション、またはブラケットで始まる行は、先程行を独立させた区間なので、これらの行にある空白をそうでない文字列に置換する。

sed 5号

改行を全部取り除く。(これはべつにsedでやる必要ないのだけど)

sed 6号

退避させていた元々の改行を復活させる。(これもべつにsedでやる必要ないのだけど)

コマンド化したものをGitHubに置いておいたよ

例によってちゃんとコマンド化したものをGistに上げておいた。ログ解析で困っているなら使ってみてね。スペースの代替文字が_では気に入らない人向けに、オプションで指定できるよにしてある本格派だ。

Apacheサーバー管理者は、これで少し幸せになれるかも。

尚、Gistに上げたものは、5号と6号のsedはtrに置き換えているので悪しからず。まぁ、全部sedでやるというのはネタだからねぇ。

257
276
12

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
257
276

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?