こんにちは、河野です。
今日もログネタです。1週間毎に保存されたログを日ごとに分けたいなと思ったので、awkでやってみました。
ログファイルはこんな感じです。わかりやすくするため1日辺り1行のログにしてみました。
1 2 3 4 5 6 7 8 |
$ cat weekly.log 192.168.1.100 - - [19/Nov/2012:03:22:36 +0900] "GET / HTTP/1.1" 301 178 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.000 192.168.1.100 - - [20/Nov/2012:03:22:41 +0900] "GET / HTTP/1.1" 200 26994 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.006 192.168.1.100 - - [21/Nov/2012:03:22:41 +0900] "GET / HTTP/1.1" 200 26994 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.003 192.168.1.100 - - [22/Nov/2012:03:23:31 +0900] "GET / HTTP/1.1" 200 26994 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.003 192.168.1.100 - - [23/Nov/2012:03:25:15 +0900] "GET / HTTP/1.1" 200 26994 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.003 192.168.1.100 - - [24/Nov/2012:03:25:15 +0900] "GET / HTTP/1.1" 200 26994 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.003 192.168.1.100 - - [25/Nov/2012:03:25:15 +0900] "GET / HTTP/1.1" 200 26994 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.003 |
これを、yyyy-mm-dd.log として7日分にしたいと思います。
日付を取得する
まずは、日付部分を取得したいと思います。awkの動作は、awkスクリプトの実行ファイルにしてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ cat split_by_date #!/usr/bin/awk -f { date = substr($4, 2, 11) print date } $ cat weekly.log | ./split_by_date 19/Nov/2012 20/Nov/2012 21/Nov/2012 22/Nov/2012 23/Nov/2012 24/Nov/2012 25/Nov/2012 |
日付を変換する
ちゃんと日付が取得できました。フォーマットが異なるので変換してみます。とりあえず月の表示がアルファベットですが、そこはいったんそのままで。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ cat split_by_date #!/usr/bin/awk -f { date = substr($4, 2, 11) split(date, params, "/") formatted_date = params[3] "-" params[2] "-" params[1] print formatted_date } $ cat weekly.log | ./split_by_date 2012-Nov-19 2012-Nov-20 2012-Nov-21 2012-Nov-22 2012-Nov-23 2012-Nov-24 2012-Nov-25 |
このファイルだけに限れば、Novを11にするだけで解決するんですが、ちゃんと対応したいと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$ cat split_by_date #!/usr/bin/awk -f function num_month(alpha_month) { return index("__,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", alpha_month) / 4 } { date = substr($4, 2, 11) split(date, params, "/") formatted_date = params[3] "-" num_month(params[2]) "-" params[1] print formatted_date } $ cat weekly.log | ./split_by_date 2012-11-19 2012-11-20 2012-11-21 2012-11-22 2012-11-23 2012-11-24 2012-11-25 |
ちゃんと変換できました!関数の仕組みは、連結した文字列からindexで位置を取得し、それを4で割っています。最初にアンダースコアを付けて、結果の数字が1~12になるよう調整しています。
ただ、もう少しだけ調整が必要で、1~9月までは1桁になってしまうので、2桁にする必要があります。sprintfを使います。
1 2 3 4 5 6 7 8 9 10 11 12 |
$ cat split_by_date #!/usr/bin/awk -f function num_month(alpha_month) { return index("__,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", alpha_month) / 4 } { date = substr($4, 2, 11) split(date, params, "/") month = sprintf("%02d", num_month(params[2])) formatted_date = params[3] "-" month "-" params[1] print formatted_date } |
個別のファイルに保存する
さて、日付が取得できるようになりましたので、後はログを日付別のファイルに保存するだけです。awkでも、シェルと同じようにリダイレクトが使えるので、受け取った行を全部日付のファイルに流し込むだけでOKです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ cat split_by_date #!/usr/bin/awk -f function num_month(alpha_month) { return index("__,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", alpha_month) / 4 } { date = substr($4, 2, 11) split(date, params, "/") month = sprintf("%02d", num_month(params[2])) filename = params[3] "-" month "-" params[1] print $0 >> filename ".log" } $ cat weekly.log | ./split_by_date |
ちゃんとログがリダイレクトされたため、今までと異なり何も出力されていません。ファイルに保存されているか確認してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
$ ls -1 2012-11-19.log 2012-11-20.log 2012-11-21.log 2012-11-22.log 2012-11-23.log 2012-11-24.log 2012-11-25.log split_by_date weekly.log $ for file in 2012*.log; do echo $file; cat $file; echo ; done 2012-11-19.log 192.168.1.100 - - [19/Nov/2012:03:22:36 +0900] "GET / HTTP/1.1" 301 178 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.000 2012-11-20.log 192.168.1.100 - - [20/Nov/2012:03:22:41 +0900] "GET / HTTP/1.1" 200 26994 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.006 2012-11-21.log 192.168.1.100 - - [21/Nov/2012:03:22:41 +0900] "GET / HTTP/1.1" 200 26994 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.003 2012-11-22.log 192.168.1.100 - - [22/Nov/2012:03:23:31 +0900] "GET / HTTP/1.1" 200 26994 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.003 2012-11-23.log 192.168.1.100 - - [23/Nov/2012:03:25:15 +0900] "GET / HTTP/1.1" 200 26994 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.003 2012-11-24.log 192.168.1.100 - - [24/Nov/2012:03:25:15 +0900] "GET / HTTP/1.1" 200 26994 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.003 2012-11-25.log 192.168.1.100 - - [25/Nov/2012:03:25:15 +0900] "GET / HTTP/1.1" 200 26994 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" "-" 0.003 |
ちゃんと分かれて保存されました!
linuxで使えるコマンドをパイプとリダイレクトで繋ぐだけでは、異なるファイルに保存するのはちょっと大変です。かといって、PythonやRubyなどLLを使うほどでは…という時にはawkが使えると思います!
Comments
とても参考になりました。ありがとうございます。