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

php getting count as per flags from text file

我正在制作一个以下列方式记录的日志文件:

[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";

日志文件可能会变得非常大。 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);

根据您在错误消息中允许的内容,您的方法可能会或可能不会产生比实际日志行更多的 errors/warnings,因为您只是在每一行中查找子字符串匹配。这样 [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";

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

$logs = file( $complete_filename );

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

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