php根据文本文件中的标志计数

时间:2016-08-12 23:16:27

标签: php file-processing

我正在制作一个日志文件,该文件以下列方式登录:

[08-12-2016 22:59:38.000000] [Error] Testing
[08-12-2016 22:59:45.000000] [Error] Testing
[08-12-2016 23:03:37.000000] [warning] Testing

我正在尝试创建一个可以读取日志文件中的总警告和总错误的函数。以下代码工作正常。问题是:有更好的方法吗?

$file = file( $complete_filename );

$totalErrors = 0;
$totalWarnings = 0;

foreach($file as $rows) {

  if(strpos( $rows,  "[warning]")) $totalWarnings ++;
  if(strpos( $rows,  "[Error]"))   $totalErrors ++;

}

echo "$totalWarnings/$totalErrors";

3 个答案:

答案 0 :(得分:2)

日志文件可能会变得非常大。 file函数将整个文件读入内存。如果文件非常大,那么PHP可能会耗尽内存并且您将收到错误。

为避免内存不足,您可以使用fopen获取文件句柄,然后使用fgets一次读取一行:

$totalErrors = 0;
$totalWarnings = 0;

$fh = fopen($complete_filename, 'rb');

if ($fh) {
    while (($line = fgets($fh, 4096)) !== false) {
        if (strpos($line, "[Error]") !== false) {
            $totalErrors++;
        }
        if (strpos($line, "[warning]") !== false) {
            $totalWarnings++;
        }
    }
}
fclose($fh);

答案 1 :(得分:2)

根据您在错误消息中可能允许的内容,您的方法可能会或可能不会产生比实际日志行更多的错误/警告,因为您只在每行中查找子字符串匹配。这样[08-12-2016 22:59:38.000000] [Error] Testing [warning]的日志行就会产生1行错误和1行警告。

您可以尝试使用正则表达式来更加勤奋。

$logResults = array_map(function($line) {
    if (preg_match('/\[.*\]\s\[(Error|warning)\]/', $line, $match)) {
        return $match[1];
    }
}, file($logFileName));

$errors = array_filter($logResults, function($l) { return $l === 'Error'; });
$warnings = array_filter($logResults, function($l) { return $l === 'warning'; });

echo "Number of errors: $errors\n";
echo "Number of warnings: $warnings\n";

答案 2 :(得分:0)

您可以使用PHP函数调用substr_count()来计算字符串中字符串匹配的数量。

$logs = file( $complete_filename );

$totalErrors = substr_count($logs, '[Error]');
$totalWarnings = substr_count($logs, '[warning]');

echo $totalWarnings . ' warnings and ' . $totalErrors . ' errors';