2015-08-14 157 views
1

我有一个脚本,通过HTTP访问日志推移,过滤出基于正则表达式百通,并把它们拷贝到另一个文件中的一些行:提高性能

param($workingdate=(get-date).ToString("yyMMdd")) 
Get-Content "access-$workingdate.log" | 
Select-string -pattern $pattern | 
Add-Content "D:\webStatistics\log\filtered-$workingdate.log" 

我的日志可能非常大(高达2GB),最多需要15分钟才能运行。我有什么可以改善上述表现的表现吗?

谢谢你的想法!

+0

相关和有用:http://stackoverflow.com/questions/31674667/is-there-a-way-to-optimise-my-powershell-function-for-removing-pattern-matches-f –

回答

1

看看这是不是比你目前的解决方案更快:

param($workingdate=(get-date).ToString("yyMMdd")) 
Get-Content "access-$workingdate.log" -ReadCount 2000 | 
foreach { $_ -match $pattern | 
    Add-Content "D:\webStatistics\log\filtered-$workingdate.log" 
} 
+0

这个代码的速度至少提高了五倍(可能是-ReadCount 2000帮助)。 谢谢! –

+0

我认为会的。通过-ReadCount和通过使用-match作为数组运算符,您可以获得效率,基本上是一次读取并过滤2000条记录,而不是1条。通过优化模式匹配可能会有更多的工作要做,通过优化正则表达式,或者如果可能的话,切换到通配符模式匹配和使用类似。 – mjolinor

2

你不显示你的模式,但我怀疑他们是问题的很大一部分。

你会想在这里寻找一个新的问题(我确定它已被问到)或其他地方寻求建立快速正则表达式模式的详细建议。

但我发现最好的建议是锚定你的模式,并避免运行不知道长度的所有字符。

因此,不要使用像path/.*/.*\.js这样的模式,而要在末尾使用带$的模式,以将其锚定到字符串的末尾。这样正则引擎可以立即告诉index.html不匹配。否则,它必须进行一些相当复杂的扫描,其中path/.js可能出现在字符串中的任何位置。这个例子当然假定文件名在日志行的末尾。

锚点也很适合线条模式的开始。模式可能看起来像^[^"]*"GET /myfile"它具有未知的运行长度,但至少它知道在找到第一个引号后不必重新搜索更多引号。 [^"]字符类允许正则表达式引擎停止,因为模式不能在第一次引用后匹配

+0

脚本通过九种不同模式的循环,生成九个单独的输出文件。有些模式和'“/ esa/ffd /”一样简单(只需查找包含此字符串的日志条目);其他人则更加复杂一些。“(/(jsummit | islands | esa)/(agd11 | esummit | gite | terd | susdv | dsd))”'。实质上,所有这些都涉及识别属于特定部门的日志条目,并且由于该网站并不是完全按照等级组织的,所以我们需要一些逻辑运算符用于正则表达式。 –

0

你也可以尝试看看使用流会加快速度。像这样的东西可能会有帮助,但我无法测试它,因为如上所述,我不确定你使用的是什么模式。

param($workingdate=(get-date).ToString("yyMMdd")) 

$file = New-Object System.IO.StreamReader -Arg "access-$workingdate.log" 
$stream = New-Object System.IO.StreamWriter -Arg "D:\webStatistics\log\filtered-$workingdate.log" 

while ($line = $file.ReadLine()) { 
    if($line -match $pattern){ 
     $stream.WriteLine($line)  
    } 
} 
$file.close() 
$stream.Close()