我有一个脚本,通过HTTP访问日志,过滤掉一些基于正则表达式模式的行,并将它们复制到另一个文件:
param($workingdate=(get-date).ToString("yyMMdd"))
Get-Content "access-$workingdate.log" |
Select-string -pattern $pattern |
Add-Content "D:webStatisticslogfiltered-$workingdate.log"
我的日志可能非常大(高达2GB),运行最多需要15分钟。我能做些什么来提高上面语句的性能吗?
谢谢你的想法!
看看这是否比你当前的解决方案更快:
param($workingdate=(get-date).ToString("yyMMdd"))
Get-Content "access-$workingdate.log" -ReadCount 2000 |
foreach { $_ -match $pattern |
Add-Content "D:webStatisticslogfiltered-$workingdate.log"
}
你没有显示你的模式,但我怀疑它们是问题的很大一部分。
你会想在这里寻找一个新的问题(我确信它已经被问到)或其他地方寻找关于构建快速正则表达式模式的详细建议。
但我发现最好的建议是固定你的模式,避免所有字符的长度未知。
因此,不要使用像path/.*/.*.js
这样的模式,而是使用末端有$
的模式来将其锚定到字符串的末端。这样regex引擎就可以立即告诉 index.html
不匹配。否则,它必须做一些相当复杂的扫描,path/
和.js
可能出现在字符串的任何地方。当然,本例假设文件名位于日志行末尾。
锚也可以很好地用于起始线模式。一个模式可能看起来像^[^"]*"GET /myfile"
,它有一个未知的运行长度,但至少它知道它不需要在找到第一个报价后重新开始搜索更多的报价。[^"]
字符类允许regex引擎停止,因为模式不能在第一个引号之后匹配。
你也可以试着看看使用流是否会加快速度。像这样的东西可能会有所帮助,尽管我无法测试它,因为,如上所述,我不确定您使用的是什么模式。
param($workingdate=(get-date).ToString("yyMMdd"))
$file = New-Object System.IO.StreamReader -Arg "access-$workingdate.log"
$stream = New-Object System.IO.StreamWriter -Arg "D:webStatisticslogfiltered-$workingdate.log"
while ($line = $file.ReadLine()) {
if($line -match $pattern){
$stream.WriteLine($line)
}
}
$file.close()
$stream.Close()