我向Powershell提出了一个菜鸟,所以请不要惩罚我:-) 所以我有一些我需要处理的相当大的日志文件(600mb),我的脚本实际上删除了那些包含“Message Received”的行,然后标记这些行并将一些令牌输出到输出文件。
脚本的逻辑很好(虽然我确定它可能更有效)但问题是,当我将行写入输出文件并且文件随后变得更大时,powershell使用的内存量也增加到记忆耗尽的重点。
任何人都可以建议我如何阻止这种情况发生?我想把日志分解成一个只有10mb的临时文件然后处理临时文件呢?
继承我的代码,你们给予的任何帮助都会很棒: - )
Get-Date | Add-Content -Path d:\scripting\logparser\testoutput.txt
$a = Get-Content D:\scripting\logparser\importsample.txt
foreach($l in $a){
#$l | Select-String -Pattern "Message Received." | Add-Content -Path d:\scripting\logparser\testoutput.txt
if
(($l | Select-String -Pattern "Message Received." -Quiet) -eq "True")
{
#Add-Content -Path d:\scripting\logparser\testoutput.txt -value $l
$var1,$var2,$var3,$var4,$var5,$var6,$var7,$var8,$var9,$var10,$var11,$var12,$var13,$var14,$var15,$var16,$var17,$var18,$var19,$var20 = [regex]::split($l,'\s+')
Add-Content -Path d:\scripting\logparser\testoutput.txt -value $var1" "$var2" "$var3" "$var4" "$var16" "$var18
}
else
{}
}
Get-Date | Add-Content -Path d:\scripting\logparser\testoutput.txt
答案 0 :(得分:7)
如果您在管道中执行所有操作,则一次只能有一个对象(在您的情况下来自文件的一行)需要在内存中。
Get-Content $inputFile | Where-Object { $_ -match "Message Received" } |
foreach-object -process {
$fields = [regex]::split($_,'\s+') # An array is created
Add-Content -path $outputFile -value [String]::Join(" ", $fields[0,1,2,3,15,17])
}
$fields[0,1,2,3,15,17]
创建一个给定索引为$fields
的数组。
这也可以在单个管道中使用表达式而不是传递给Select-Object的属性名称来完成,但不太清楚。
答案 1 :(得分:2)
一个有效的PowerShell示例:
$csvFile = "c:\test.txt"
$file_reader = [System.IO.File]::OpenText($csvFile)
$row = "";
while(($row = $file_reader.ReadLine()) -ne $null)
{
# do something with '$row'
Write-Host row: $row
}
$file_reader.Close()
答案 2 :(得分:0)
您有效地将整个日志文件存储在内存中,而不是逐位顺序访问它。
假设您的日志文件对于每个条目(可能是新行)都有一些内部分隔符,您每次都会在每个条目中读取内容分隔符,而不是在内存中保留更多内容而非绝对必要。
你将无法依赖内置的PowerShell东西,因为它会造成愚蠢的影响。
你必须为我的代码示例道歉,我的PowerShell有点生疏。
var $reader = Create-Object "System.IO.StreamReader" testoutput.txt
var $s = ""
while(($s = reader.ReadLine())!=null)
{
// do something with '$s'
// which would contain individual log entries.
}
$reader.Close()