まさはる's Weblog

まさはる's Weblog
Macintoshとオーディオの話題

2004年7月 4日

Perlを使ってみました

Category : Terminal / Posted at 2004年7月 4日 17:47

 C'S SERVER Personalのサブドメインサービスはアクセスログを取得できるので、面白半分でエディタで開いてみたところ、あまりの量の多さにびっくり(これまで見たことなかったもので...(^_^;)。よく見ると、1ファイルの転送が1行で記録されており、トップページに1度アクセスしただけで20行程のログ...。こりゃ人間の見るものじゃないなと思い、リンク元が同じものを1行にまとめるプログラムを作ってみることにしました。

 プログラムの作成には、文字列の扱いが簡単にできそうで、かつインターネットで広く使われているPerl*1を使うことにしました。早速、オライリー・ジャパン初めてのPerl 第3版*2(通称「リャマ本」)を買ってきて、本を見ながら作ってみました。

#!/usr/bin/perl -w
use strict;
# ログファイルの整理プログラム log.pl [-dhrDHR] ver.1.0
# オプション d:date, h:host, r:referer を整形して出力
#            D:date, H:host, R:referer を整形せずに出力
 
# 入力するログファイルのフォーマット
# host ident authuser date "request" status bytes "referer"
# "user-agent"\n
# date = [day/month/year:hour:minute:second zone]
# day 2桁, month 3文字, year 4桁, hour 2桁, minute 2桁, second 2桁
# zone (+|-)4桁
 
# 出力するログファイルの標準フォーマット(-dhr)
# date host referer
# date = day/month/year:hour:minute:second
# day 2桁, month 3文字, year 4桁, hour 2桁, minute 2桁, second 2桁 計20桁
# host 後半20文字
# referer 前半37文字,自分のサイトアドレスは / に置き換える
 
my $my_site = 'http://masaharu.la.coocan.jp/blog/';   # 自分のサイトアドレス
my $check = 10;                                # 遡ってチェックする行数
my @before_host = (' ') x $check;
my @before_referer = (' ') x $check;
my $option = '-dhr';
if (@ARGV) {
    if ($ARGV[0] =~ /^-[dhrDHR]/) {
        $option = shift @ARGV;
    }
}
 
foreach (<STDIN>) {
    /(^\S+).+(\[\S+ \S+\]) "[^"]+".+"([^"]+)" "[^"]+"\n/;
    my $host = $1;
    my $date = $2;
    my $referer = $3;
 
    # 遡ったチェック行数内で host と referer が同じ場合は出力しない
    my $out = 1;                               # 初期値 = 出力する
    foreach (0..$check - 1) {
        if (($host eq $before_host[$_]) && 
        ($referer eq $before_referer[$_])) {
            $out = 0;
            last;
        }
    }
    pop @before_host;                          # 配列の末尾を削除
    pop @before_referer;
    unshift @before_host, $host;               # 配列の先頭に追加
    unshift @before_referer, $referer;
 
    # 出力
    if ($out == 1) {
        if ($option =~ /^-.*d/) {              # 秒まで
            print substr($date, 1, 20), ' ';
        } elsif ($option =~ /^-.*D/) {         # そのまま
            print "$date ";
        }
        if ($option =~ /^-.*h/) {              # 後半20文字
            printf "%20.20s ", substr($host, -20, 20);
        } elsif ($option =~ /^-.*H/) {         # そのまま
            print "$host ";
        }
        if ($option =~ /^-.*r/) {
            if ($referer =~ /^($my_site)/) {   # 前半36文字
                print '/', substr($referer, length($my_site), 36);
            } else {                           # 前半37文字
                print substr($referer, 0, 37);
            }
        } elsif ($option =~ /^-.*R/) {         # そのまま
            print $referer;
        }
        print "\n";
    }
}

 コメント、変数の宣言及びオプション処理を除くと、10行有るか無いかって感じですね。これを実行してみるとこんな感じに...。

実行結果
7月2日のログを入れてみました

 ソートしてグラフを描かないと使い物にならないという声が聞こえてきそうですが、うちのサイトの場合、1日分だとターミナルの1ページに収まってしまい、これで十分という噂も...(^_^;
 次回は、1週間分ぐらいのデータで、グラフが描けるようなプログラムを作ってみようと思います。*3

*1 Perlを知ったのは随分前(きっとPerlの出始めの頃...)で、当時購読していた月刊アスキーに紹介記事が載っていました。その時は便利そうだなあと思いましたが、私の周りには動かせる環境が全くありませんでした。
*2 この本は、内容が丁寧で分かり易く、冗談混じりで非常に面白く読むことができます。Perl入門者には超オススメです。
*3 こういうのを(もっとレベルの高いプログラムでの話ですが...)リャマ本には「車輪の再発明」と皮肉られています。C'S SERVER PersonalではAnalogによるアクセス解析が可能なので、自分でプログラムを書く必要はないのですが、せっかくPerlを覚えたので練習にと...(^_^;
このページのトップに戻る