現在の位置: ホーム> 最新記事一覧> ログファイルのIP、時間、その他のフィールドの統一形式

ログファイルのIP、時間、その他のフィールドの統一形式

M66 2025-05-18

サーバーログファイルを処理するとき、一貫性のない形式で問題が発生することがよくあります。たとえば、IPアドレスには主要なゼロがあり、タイムスタンプ形式は一貫性がなく、リクエストパスにはさまざまなパラメーターがある場合があります。これらのフィールドを均一に処理するために、 preg_replace_callback_arrayは非常に強力なツールであり、異なるコールバック関数を複数の正規表現に個別にバインドし、横断で複雑な交換ロジックを完全にバインドできます。

この記事では、 preg_replace_callback_arrayを使用して、ログ内のIPと時間フィールドを均一にフォーマットする方法を紹介します。

サンプルログ形式

次のログコンテンツ(簡素化されたバージョン)があるとします。

 127.000.000.001 - - [21/Apr/2025:15:32:01 +0000] "GET /index.php?id=123 HTTP/1.1" 200
192.168.1.10 - - [21-Apr-2025 15:32:01] "POST /submit.php HTTP/1.1" 404

私たちは願っています:

  • IPアドレスを正規化します(主要なゼロの削除)。

  • yyyy-mm-dd hh:mm:ss形式への時間を統合します。

  • オプション:PATHのマスクパラメーター、たとえば/index.php?id=123→ /index.php

preg_replace_callback_arrayを使用した実装

<?php

$log = <<<LOG
127.000.000.001 - - [21/Apr/2025:15:32:01 +0000] "GET /index.php?id=123 HTTP/1.1" 200
192.168.1.10 - - [21-Apr-2025 15:32:01] "POST /submit.php HTTP/1.1" 404
LOG;

// 通常および対応する処理コールバックを定義します
$patterns = [
    // IP アドレスフォーマット:主要なゼロを削除します
    '/\b(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\b/' => function ($matches) {
        return implode('.', array_map('intval', array_slice($matches, 1, 4)));
    },

    // Apache スタイルタイムスタンプ [21/Apr/2025:15:32:01 +0000]
    '/\[(\d{2})\/(\w{3})\/(\d{4}):(\d{2}):(\d{2}):(\d{2}) [+\-]\d{4}\]/' => function ($matches) {
        $monthMap = [
            'Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04',
            'May' => '05', 'Jun' => '06', 'Jul' => '07', 'Aug' => '08',
            'Sep' => '09', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12'
        ];
        return sprintf('%s-%s-%s %s:%s:%s',
            $matches[3],                         // 年
            $monthMap[$matches[2]] ?? '01',     // 月
            $matches[1],                         // 日
            $matches[4], $matches[5], $matches[6]
        );
    },

    // ログ形式の別の時間 [21-Apr-2025 15:32:01]
    '/(\d{2})-(\w{3})-(\d{4}) (\d{2}):(\d{2}):(\d{2})/' => function ($matches) {
        $monthMap = [
            'Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04',
            'May' => '05', 'Jun' => '06', 'Jul' => '07', 'Aug' => '08',
            'Sep' => '09', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12'
        ];
        return sprintf('%s-%s-%s %s:%s:%s',
            $matches[3],
            $monthMap[$matches[2]] ?? '01',
            $matches[1],
            $matches[4], $matches[5], $matches[6]
        );
    },

    // 取り除く URL パラメーター(のように /index.php?id=123 → /index.php)
    '#(GET|POST|PUT|DELETE|HEAD) (/[\w\-\/\.]+)(\?[^\s"]*)?#' => function ($matches) {
        return $matches[1] . ' ' . $matches[2];
    }
];

// アプリケーションの交換
$formatted = preg_replace_callback_array($patterns, $log);

// 出力結果
echo nl2br(htmlspecialchars($formatted));
?>

出力結果

上記のスクリプトを実行した後、ログコンテンツは次のようにフォーマットされます。

 127.0.0.1 - - 2025-04-21 15:32:01 "GET /index.php HTTP/1.1" 200  
192.168.1.10 - - 2025-04-21 15:32:01 "POST /submit.php HTTP/1.1" 404

まとめ

preg_replace_callback_arrayを使用すると、非常にエレガントな方法でログ内の異なる形式で複数のフィールドを処理できます。その利点は、複数のモードを一度に処理することです。各モードには独自のコールバック機能が独立しており、明確なロジックと簡単なメンテナンスがあります。