我正在读取日志文件,这些文件可以是任何内容,从一个小日志文件到8-10mb的日志。典型的尺寸可能是1mb。现在关键的是,im查找的关键字通常在文档末尾附近,在95%的情况下可能是这样。然后我在关键字后面提取1000个字符。
如果我使用这种方法:
$lines = explode("n",$body);
$reversed = array_reverse($lines);
foreach($reversed AS $line) {
// Search for my keyword
}
它会比使用更有效吗
$pos = stripos($body,$keyword);
$snippet_pre = substr($body, $pos, 1000);
我不确定的是,stripos是否只是开始一次搜索文档中的1个字符,所以理论上,如果关键字后面有10000个字符,那么我就不必将这些字符读入内存,而第一个选项必须将所有内容读入内存,即使它可能只需要最后100行,我可以将其更改为将100行读入内存吗,然后再搜索101-200行,如果前100行不成功,或者查询太轻以至于无关紧要。
我有第二个问题,这假设reverse_array是最好的方法,在我找到关键字后,我如何提取接下来的1000个字符,这是我可悲的尝试
$body = $this_is_the_log_content;
$lines = explode("n",$body);
$reversed = array_reverse($lines);
foreach($reversed AS $line) {
$pos = stripos($line,$keyword);
$snippet_pre = substr($line, $pos, 1000);
}
Why i don't think that will work is because each $line might only be a few hundred characters so would the better solution be to explode it every say 2,000 lines and also keep the previous $line as a backup variable so something like this.
$body = $this_is_the_log_content;
$lines = str_split($body, 2000);
$reversed = array_reverse($lines);
$previous_line = $line;
foreach($reversed AS $line) {
$pos = stripos($line,$keyword);
if ($pos) {
$line = $previous_line . ' ' . $line;
$pos1 = stripos($line,$keyword);
$snippet_pre = substr($line, $pos, 1000);
}
}
我可能过于复杂了?
我强烈考虑使用grep
这样的工具。您可以从PHP调用这个命令行工具,并使用它在文件中搜索您要查找的单词,并执行以下操作:给您匹配行的字节偏移量,给您一个匹配行加上尾部上下文行,等等。
这是grep手册的链接。http://unixhelp.ed.ac.uk/CGI/man-cgi?grep
在命令行上玩一点命令,以获得所需的方式,然后使用exec()
、passthru()
或类似的方法从PHP调用它,具体取决于您需要如何捕获/显示内容。
或者,您可以简单地将指针放在末尾的文件fopen()
,并在文件中向前移动文件指针,同时使用fseek()
搜索字符串。一旦找到指针,就可以从该偏移量读取文件,直到到达文件末尾或日志条目的数量。
这两种方法中的任何一种都可能比将整个日志文件读取到内存中然后尝试使用它更可取
另一个需要考虑的问题是1000个字符是否有意义。通常,日志文件的行长度会有所不同。在我看来,您应该更关心从日志文件中获取下一个X行,而不是下一个Y字符。如果一行有2000个字符,你是说你只想得到其中的一半吗?这可能根本没有意义。