サーバーログファイルを処理するとき、一貫性のない形式で問題が発生することがよくあります。たとえば、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
<?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を使用すると、非常にエレガントな方法でログ内の異なる形式で複数のフィールドを処理できます。その利点は、複数のモードを一度に処理することです。各モードには独自のコールバック機能が独立しており、明確なロジックと簡単なメンテナンスがあります。