让日志文件不时缺少“新行”
2010.12.17 04:26 127.0.0.1 user:user1 region:NA ERROR: Invalid password
2010.12.17 04:27 127.0.0.1 user:user1 region:AP ERROR: Invalid password
2010.12.17 04:32 127.0.0.12010.12.17 04:32 127.0.0.1 user:user1 region:AP ERROR: Invalid password
2010.12.17 04:32 127.0.0.1 user:user1 region:NA ERROR: Invalid password
在上面第三行的例子中:
2010.12.17 04:32 127.0.0.1
应该在一行
和2010.12.17 04:32 127.0.0.1 user:user1 region:AP ERROR: Invalid password
应该在另一行。
我需要将行读入数组,就像file()正在做的那样,但是使用了更正的行。
我无法通过在需要的地方插入新行来触摸文件本身来纠正它。
我在考虑fread,但这会将整个文件内容读入一个字符串。也许我应该解析这个大字符串..?
您是否更了解如何实现这一目标?
答案 0 :(得分:2)
如果您可以将整个文件加载到内存中,则可以根据行的开头使用preg_split()
:
$result = preg_split('/(?=\d{4}\.\d{2}\.\d{2})/m', $body);
print_r($result); // ignore first array element
答案 1 :(得分:0)
您必须找到一种方法来检测这些换行符的位置,以便您可以将数据读取到这些位置。这意味着您需要查看文件行格式,并尝试根据该格式进行阅读。最简单的方法是使用正则表达式,它将尝试匹配尽可能多的文本,直到该模式开始下一行。匹配应考虑可能存在行结束标记。
幸运的是,日志的每一行都以一个时间戳开始,该时间戳在整个文件中的变化不大。通常,日志涵盖一天,因此您可以将regexp作为日志的第一个字符,这必须是第一行的开头。
$file = fopen($logname, "r");
$content = array();
$date = fread($file, 9); // date length
fseek($file, 0);
$pattern = $date.".*?(".$date.")?";
while ($data = fread($file, 4096)){
$buff .= $data;
while (preg_match($pattern, $data,$matches = array())){
$content[] = $matches[0];
$buff = substr($buff, strlen($matches[0]));
}
} // end of file
if (strlen($buff)){
echo ”extra data at end of log : " . $buff;
}
您应该能够根据日志时间戳格式调整该代码。
答案 2 :(得分:0)
根据Jack的回答,编写了一个使用fopen和fgets的代码:fgets逐行读取,我猜它不会像使用file()或fread()那样加载内存。
$flog_path="/srv/www/****.log";
$ftemp = fopen($flog_path,"r");
while ($s=fgets($ftemp)) {
$elem=preg_split('/(?=\d{4}\.\d{2}\.\d{2})/m', $s);
foreach (array_filter($elem) as $v) $result[] = trim($v);
}