我有一个通过HTTP访问日志的脚本,根据正则表达式patern过滤掉一些行并将它们复制到另一个文件中:
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 :(得分:2)
你没有显示你的模式,但我怀疑它们是问题的主要部分。
您需要在此处寻找新问题(我确信已经有人问过)或其他地方,以获取有关构建快速正则表达式模式的详细建议。
但我发现最好的建议是锚定你的模式,避免所有角色的未知长度。
因此,不是像path/.*/.*\.js
这样的模式,而是在末尾使用一个$
来将其锚定到字符串的末尾。这样,正则表达式引擎可以立即告诉 index.html
不匹配。否则,它必须进行一些相当复杂的扫描,path/
和.js
可能会出现在字符串中的任何位置。此示例当然假定文件名位于日志行的末尾。
锚点也适用于线条模式的开始。模式可能看起来像^[^"]*"GET /myfile"
具有未知的运行长度,但至少它知道在找到第一个之后它不必重新搜索更多的引号。 [^"]
字符类允许正则表达式引擎停止,因为在第一个引号后模式不能匹配
答案 1 :(得分: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"
}
答案 2 :(得分: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()