如何通过PowerShell有效地从日志文件中查找和解析最后一行文本?

时间:2016-05-11 17:24:00

标签: powershell

我有一个非常大的日志文件。我需要找出最后一个" WARN"有效地在该文件中划线(即:从末尾读取),解析它,并将其作为对象返回"日期"字段(日期时间类型),"级别"字段和"描述"字段

有什么建议吗?

这是文件的样子

[Mon Dec 14 14:57:53 2015] [notice] Child 6180: Acquired the start mutex.
[Mon Dec 14 14:57:53 2015] [notice] Child 6180: Starting 150 worker threads.
[Mon Dec 14 15:04:43 2015] [warn] pid file C:/Program Files (x86)/Citrix/XTE/logs/xte.pid overwritten -- Unclean shutdown of previous Apache run?
[Mon Dec 14 15:04:43 2015] [notice] Server built: May 27 2011 16:04:42
[Mon Dec 14 15:04:43 2015] [notice] Parent: Created child process 5608

编辑:此命令必须查看文件内部,按搜索条件查找最后一个匹配行,返回该行,然后"停止"。可能的重复问题在很多方面都有所不同:我的脚本不能简单地坐在那里等待线出现 - 它需要运行,尽快获得线路,然后离开。此外,它需要通过子字符串搜索它,最后它需要返回一个DateTime和其他分解的字段。谢谢你没有投票来结束这个问题。

3 个答案:

答案 0 :(得分:0)

以原始Stream打开文件,从末尾寻找“体面”的块大小(比如1 MB),然后在结果字节中搜索“warn”的二进制表示,直到找到最后一个实例(我假设您事先知道编码)。如果找到它,请扫描行终止符。如果找不到,请找回1 + 1 MB然后再去。重复,直到你开始寻找。

如果整个文件中没有“警告”,这将比按顺序读取文件慢,但是如果你确定你想要的那一行接近结尾,这可以很快终止。要做的重要事情是将文件作为带有StreamReader的文本读取,因为您失去了任意搜索的能力。

实际上,正确地获取这个想法的代码更为复杂。这个操作的难度不是由于PowerShell中的任何东西 - 在任何语言中都没有简单的方法可以做到这一点,因为在我知道的任何文件系统中,反向读取文件并不是一种有效的操作。

答案 1 :(得分:0)

我这样接近:

ParentPicture

答案 2 :(得分:-1)

这肯定不会有效率。 PowerShell和C#(以及其他所有内容)中的所有内容都是围绕阅读前进而非后退而构建的。考虑到这一点以及您甚至不知道最后一行的位置这一事实,除非您想花几个小时编写自己的ReverseStreamReader,否则我认为没有办法避免处理整个文件。

假设文件大于RAM - 这使得Get-Content不切实际,IMO - 我可能会做类似的事情:

$LineNumber = [uint64]0;
$StreamReader = New-Object System.IO.StreamReader -ArgumentList "C:\LogFile.log"
$SearchPattern = [Regex]::Escape('[warn]');
while ($Line = $StreamReader.ReadLine()) {
    $LineNumber++;
    if ($Line -match $SearchPattern) {
        $LastLineNumber = $LineNumber;
        $LastLineMatch = $Line;
    }
}
$StreamReader.Close()

$LastLineNumber
$LastLineMatch

解析该行可能涉及很多String.IndexOf()和String.Substring()。将日期转换为DateTime应该这样完成:

[datetime]::ParseExact('Mon Dec 14 15:04:43 2015','ddd MMM dd HH:mm:ss yyyy',[System.Globalization.CultureInfo]::InvariantCulture,[System.Globalization.DateTimeStyles]::None);

我选择-match超过-like,因为据我所知,它实际上表现更好。那可能只是我的系统。