像尾一样反向日志
Reverse log like tail
我想撤销我的系统日志。
我的系统日志是这样的:
[ 2016-03-17T15:52:00+08:00 ] 0.0.0.0 /Pwebshell/index.php/Log/GetLog
INFO: [ route_check ] --START--
INFO: CheckRoute Behavior ::run [ RunTime:0.001000s ]
INFO: [ route_check ] --END-- [ RunTime:0.001000s ]
INFO: [ app_begin ] --START--
INFO: ReadHtmlCache Behavior ::run [ RunTime:0.001000s ]
INFO: [ app_begin ] --END-- [ RunTime:0.001000s ]
[ 2016-03-17T15:52:16+08:00 ] 0.0.0.0 /Pwebshell/index.php/Log/GetLog
INFO: [ route_check ] --START--
INFO: CheckRoute Behavior ::run [ RunTime:0.000000s ]
INFO: [ route_check ] --END-- [ RunTime:0.001000s ]
INFO: [ app_begin ] --START--
INFO: ReadHtmlCache Behavior ::run [ RunTime:0.000000s ]
INFO: [ app_begin ] --END-- [ RunTime:0.000000s ]
我想这样打印:
[ 2016-03-17T15:52:16+08:00 ] 0.0.0.0 /Pwebshell/index.php/Log/GetLog
INFO: [ route_check ] --START--
INFO: CheckRoute Behavior ::run [ RunTime:0.000000s ]
INFO: [ route_check ] --END-- [ RunTime:0.001000s ]
INFO: [ app_begin ] --START--
INFO: ReadHtmlCache Behavior ::run [ RunTime:0.000000s ]
INFO: [ app_begin ] --END-- [ RunTime:0.000000s ]
[ 2016-03-17T15:52:00+08:00 ] 0.0.0.0 /Pwebshell/index.php/Log/GetLog
INFO: [ route_check ] --START--
INFO: CheckRoute Behavior ::run [ RunTime:0.001000s ]
INFO: [ route_check ] --END-- [ RunTime:0.001000s ]
INFO: [ app_begin ] --START--
INFO: ReadHtmlCache Behavior ::run [ RunTime:0.001000s ]
INFO: [ app_begin ] --END-- [ RunTime:0.001000s ]
到目前为止我尝试过的:
1 首先,我使用 file_get_contents
阅读日志
$content = file_get_contents('log');
2 然后我使用正则表达式 select 条目。
preg_match_all('#(\[\s+\d{4}\-\d{2}\-\d{2}.*\].*?)\[\s+\d{4}\-\d{2}\-\d{2}#s', $content, $matches);
3我会用array_reverse
反转日志
但是 $matches
没有被正则表达式 select 正确编辑。
正则表达式存在三个不同的问题:
- 您需要第一个
.*
不贪心,否则它将匹配文件中的最后一个 ]
。
- 您的正则表达式与最后一个条目不匹配,因为它后面没有另一个条目。
- 每个匹配 "captures" 匹配的文本,包括以下
\[\s+\d{4}\-\d{2}\-\d{2}
(即它捕获下一个条目的开始)。这意味着只会返回部分匹配项。要纠正这个问题,我们需要使用 (?=...)
. 将最后一部分转换为前瞻断言
像下面这样的东西应该可以解决这三个问题。
preg_match_all('#(\[\s+\d{4}\-\d{2}\-\d{2}.*?\].*?)(?=\[\s+\d{4}\-\d{2}\-\d{2}|$)#s', $content, $matches);
但是您的条目似乎被双行分隔。为什么不只是拆分这些日志?假设您不会在日志数据中自然地获得双换行,这将更易于阅读、更快且更不容易出错。
以下内容适用于 Linux:
$lines = explode("\n\n", $content);
$lines = array_reverse($lines);
echo implode("\n\n", $lines);
在 Windows 上,您可能需要将 \n\n
替换为 \r\n\r\n
。
一种改进的解决方案,无论换行符的类型如何,都可以使用,允许在换行符之间使用白色 space,并且使用系统默认的行尾输出可能如下所示:
$lines = preg_split("#\r?\n\s*\n#", $content);
$lines = array_reverse($lines);
echo implode(PHP_EOL . PHP_EOL, $lines);
这还将处理这样一个事实,即您的日志内容有时似乎包含两个以上的换行分隔条目。
我想撤销我的系统日志。
我的系统日志是这样的:
[ 2016-03-17T15:52:00+08:00 ] 0.0.0.0 /Pwebshell/index.php/Log/GetLog
INFO: [ route_check ] --START--
INFO: CheckRoute Behavior ::run [ RunTime:0.001000s ]
INFO: [ route_check ] --END-- [ RunTime:0.001000s ]
INFO: [ app_begin ] --START--
INFO: ReadHtmlCache Behavior ::run [ RunTime:0.001000s ]
INFO: [ app_begin ] --END-- [ RunTime:0.001000s ]
[ 2016-03-17T15:52:16+08:00 ] 0.0.0.0 /Pwebshell/index.php/Log/GetLog
INFO: [ route_check ] --START--
INFO: CheckRoute Behavior ::run [ RunTime:0.000000s ]
INFO: [ route_check ] --END-- [ RunTime:0.001000s ]
INFO: [ app_begin ] --START--
INFO: ReadHtmlCache Behavior ::run [ RunTime:0.000000s ]
INFO: [ app_begin ] --END-- [ RunTime:0.000000s ]
我想这样打印:
[ 2016-03-17T15:52:16+08:00 ] 0.0.0.0 /Pwebshell/index.php/Log/GetLog
INFO: [ route_check ] --START--
INFO: CheckRoute Behavior ::run [ RunTime:0.000000s ]
INFO: [ route_check ] --END-- [ RunTime:0.001000s ]
INFO: [ app_begin ] --START--
INFO: ReadHtmlCache Behavior ::run [ RunTime:0.000000s ]
INFO: [ app_begin ] --END-- [ RunTime:0.000000s ]
[ 2016-03-17T15:52:00+08:00 ] 0.0.0.0 /Pwebshell/index.php/Log/GetLog
INFO: [ route_check ] --START--
INFO: CheckRoute Behavior ::run [ RunTime:0.001000s ]
INFO: [ route_check ] --END-- [ RunTime:0.001000s ]
INFO: [ app_begin ] --START--
INFO: ReadHtmlCache Behavior ::run [ RunTime:0.001000s ]
INFO: [ app_begin ] --END-- [ RunTime:0.001000s ]
到目前为止我尝试过的:
1 首先,我使用 file_get_contents
$content = file_get_contents('log');
2 然后我使用正则表达式 select 条目。
preg_match_all('#(\[\s+\d{4}\-\d{2}\-\d{2}.*\].*?)\[\s+\d{4}\-\d{2}\-\d{2}#s', $content, $matches);
3我会用array_reverse
反转日志
但是 $matches
没有被正则表达式 select 正确编辑。
正则表达式存在三个不同的问题:
- 您需要第一个
.*
不贪心,否则它将匹配文件中的最后一个]
。 - 您的正则表达式与最后一个条目不匹配,因为它后面没有另一个条目。
- 每个匹配 "captures" 匹配的文本,包括以下
\[\s+\d{4}\-\d{2}\-\d{2}
(即它捕获下一个条目的开始)。这意味着只会返回部分匹配项。要纠正这个问题,我们需要使用(?=...)
. 将最后一部分转换为前瞻断言
像下面这样的东西应该可以解决这三个问题。
preg_match_all('#(\[\s+\d{4}\-\d{2}\-\d{2}.*?\].*?)(?=\[\s+\d{4}\-\d{2}\-\d{2}|$)#s', $content, $matches);
但是您的条目似乎被双行分隔。为什么不只是拆分这些日志?假设您不会在日志数据中自然地获得双换行,这将更易于阅读、更快且更不容易出错。
以下内容适用于 Linux:
$lines = explode("\n\n", $content);
$lines = array_reverse($lines);
echo implode("\n\n", $lines);
在 Windows 上,您可能需要将 \n\n
替换为 \r\n\r\n
。
一种改进的解决方案,无论换行符的类型如何,都可以使用,允许在换行符之间使用白色 space,并且使用系统默认的行尾输出可能如下所示:
$lines = preg_split("#\r?\n\s*\n#", $content);
$lines = array_reverse($lines);
echo implode(PHP_EOL . PHP_EOL, $lines);
这还将处理这样一个事实,即您的日志内容有时似乎包含两个以上的换行分隔条目。