提高 PowerShell 过滤语句的性能
Improving performance on PowerShell filtering statement
我有一个脚本可以通过 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 分钟才能 运行。有什么我可以做的来提高上述陈述的表现吗?
谢谢你的想法!
看看这是否比您当前的解决方案更快:
param($workingdate=(get-date).ToString("yyMMdd"))
Get-Content "access-$workingdate.log" -ReadCount 2000 |
foreach { $_ -match $pattern |
Add-Content "D:\webStatistics\log\filtered-$workingdate.log"
}
你没有显示你的模式,但我怀疑它们是问题的很大一部分。
您会想在这里(我相信有人问过)或其他地方寻找新问题,以获得有关构建快速正则表达式模式的详细建议。
但我发现最好的建议是锚定您的模式并避免 运行 所有字符的长度未知。
因此,不要使用像 path/.*/.*\.js
这样的模式,而要使用末尾带有 $
的模式来将其锚定到字符串的末尾。这样正则表达式引擎可以立即 告诉 index.html
不匹配。否则它必须做一些相当复杂的扫描 path/
和 .js
可能出现在字符串的任何地方。这个例子当然假设文件名在日志行的末尾。
锚点也适用于行首模式。一个模式可能看起来像 ^[^"]*"GET /myfile"
具有未知的 运行 长度,但至少它知道它不必在找到第一个引号后重新开始搜索更多引号。 [^"]
字符 class 允许正则表达式引擎停止,因为模式 不能 在第一个引号后匹配。
您也可以尝试看看使用流是否会加快速度。这样的事情可能会有所帮助,尽管我无法对其进行测试,因为如上所述,我不确定您使用的是什么模式。
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()
我有一个脚本可以通过 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 分钟才能 运行。有什么我可以做的来提高上述陈述的表现吗?
谢谢你的想法!
看看这是否比您当前的解决方案更快:
param($workingdate=(get-date).ToString("yyMMdd"))
Get-Content "access-$workingdate.log" -ReadCount 2000 |
foreach { $_ -match $pattern |
Add-Content "D:\webStatistics\log\filtered-$workingdate.log"
}
你没有显示你的模式,但我怀疑它们是问题的很大一部分。
您会想在这里(我相信有人问过)或其他地方寻找新问题,以获得有关构建快速正则表达式模式的详细建议。
但我发现最好的建议是锚定您的模式并避免 运行 所有字符的长度未知。
因此,不要使用像 path/.*/.*\.js
这样的模式,而要使用末尾带有 $
的模式来将其锚定到字符串的末尾。这样正则表达式引擎可以立即 告诉 index.html
不匹配。否则它必须做一些相当复杂的扫描 path/
和 .js
可能出现在字符串的任何地方。这个例子当然假设文件名在日志行的末尾。
锚点也适用于行首模式。一个模式可能看起来像 ^[^"]*"GET /myfile"
具有未知的 运行 长度,但至少它知道它不必在找到第一个引号后重新开始搜索更多引号。 [^"]
字符 class 允许正则表达式引擎停止,因为模式 不能 在第一个引号后匹配。
您也可以尝试看看使用流是否会加快速度。这样的事情可能会有所帮助,尽管我无法对其进行测试,因为如上所述,我不确定您使用的是什么模式。
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()