Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何通过PowerShell有效地查找和解析日志文件中的最后一行文本?_Powershell - Fatal编程技术网

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

如何通过PowerShell有效地查找和解析日志文件中的最后一行文本?,powershell,Powershell,我有一个很大的日志文件。我需要有效地找出文件中最后一行“警告”(即:从末尾读取),解析它,并将其作为带有“日期”字段(日期时间类型)、“级别”字段和“描述”字段的对象返回 有什么建议吗 下面是该文件的外观 [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 threa

我有一个很大的日志文件。我需要有效地找出文件中最后一行“警告”(即:从末尾读取),解析它,并将其作为带有“日期”字段(日期时间类型)、“级别”字段和“描述”字段的对象返回

有什么建议吗

下面是该文件的外观

[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和其他分解的字段。感谢您没有投票结束此问题。

这肯定不会有效率。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]::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
,因为据我所知,它实际上性能更好。但是,这可能只是我的系统。

将文件作为原始
流打开,从末尾开始寻找“合适”的块大小(比如说1 MB),然后搜索结果字节以查找“warn”的二进制表示形式,直到找到最后一个实例(我假设您事先知道编码)。如果找到了,请扫描线路终端。如果找不到它,请返回1+1MB并再次查找。重复上述步骤,直到找到开始

如果在整个文件中没有“警告”,这将比按顺序读取文件慢,但是如果您确定在接近末尾时有一行您想要的代码,那么这可能会很快终止。基本的做法是不要使用
StreamReader
将文件作为文本读取,因为您将失去任意搜索的能力


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

我会这样做:

get-content $file -ReadCount 3000 |
 ForEach-Object {
  if ($_ -like '*warn*')
    {$Lastfound = $_}
 }

 ($Lastfound -like '*warn*')[-1]

其可能的副本在任何方面都不等同。我需要根据搜索条件找到最后一个匹配行,而不是获取最后一行。此外,还需要解析out DateTime。一般来说,请不要投票通过Close,因为这是一个可以获得您所编写的代码的帮助的地方。这不是一个要求为你写剧本的地方。我很惊讶一个拥有10000+声誉的人会发布这个!与的唯一实质性区别是,您需要根据内容进行过滤——与快速反向扫描文件相比,分解字段是一项微不足道的工作。“然而,这是一个实质性的区别。”TonyHinkle表示感谢。我曾尝试编写PowerShell脚本,但都失败了,因为我根本不了解PowerShell,所以我很尴尬,无法发布这些脚本;)