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 分钟。我能做些什么来提高上述语句的性能吗?

谢谢你的想法!

4

3 回答 3

3

看看这是否比您当前的解决方案更快:

param($workingdate=(get-date).ToString("yyMMdd"))
Get-Content "access-$workingdate.log" -ReadCount 2000 |
 foreach { $_ -match $pattern | 
  Add-Content "D:\webStatistics\log\filtered-$workingdate.log"
 }
于 2015-08-14T00:22:36.323 回答
2

你没有展示你的模式,但我怀疑它们是问题的很大一部分。

你会想在这里寻找一个新问题(我相信它已经被问过了)或其他地方,以获得有关构建快速正则表达式模式的详细建议。

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

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

锚点也适用于线型的开始。一个模式可能看起来像^[^"]*"GET /myfile"That has a unknown run length 但至少它知道它不必在找到第一个引号后重新开始搜索更多引号。字符类允许正[^"]则表达式引擎停止,因为模式在第一个引号之后无法匹配。

于 2015-08-14T00:47:25.597 回答
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()
于 2015-08-14T01:39:40.060 回答