提高PowerShell过滤语句

时间:2015-08-14 00:14:49

标签: regex performance powershell filtering select-string

我有一个通过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分钟才能运行。有什么我可以做的改进上述声明的表现吗?

感谢您的想法!

3 个答案:

答案 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()