需要帮助改善PowerShell中分隔的文本解析脚本的执行

问题描述:

我有必要通过大型管道分隔的文件解析来算,其第5列符合,不符合我的标准的记录数。需要帮助改善PowerShell中分隔的文本解析脚本的执行

PS C:\temp> gc .\items.txt -readcount 1000 | ` 
    ? { $_ -notlike "HEAD" } | ` 
    % { foreach ($s in $_) { $s.split("|")[4] } } | ` 
    group -property {$_ -ge 256} -noelement | ` 
    ft –autosize 

此命令我想要做什么,这样返回的输出:

 
    Count Name 
    ----- ---- 
1129339 True 
2013703 False 

然而,对于一个500 MB的测试文件,这个命令需要约5.5钟如通过测量命令测量运行。一个典型的文件超过2GB,等待20分钟以上的时间不合需要很长。

你看到的方式,以提高该命令的性能?

例如,有没有办法来确定获取内容的ReadCount最佳值?没有它,完成相同的文件需要8.8分钟。

+0

您是否试过StreamReader?我认为Get-Content会在完成任何事情之前将整个文件加载到内存中。 – Gisli 2012-01-17 21:52:25

+0

你的意思是通过导入System.IO? – neontapir 2012-01-17 21:59:23

+0

是的,如果可以的话,请使用.net框架。我曾经习惯读取SQL Server生成的大型日志文件,结果良好。我不知道PowerShell中有任何其他方式来有效地读取大文件,但我不是专家。 – Gisli 2012-01-17 22:08:59

您是否尝试过的StreamReader?我认为Get-Content会在完成任何事情之前将整个文件加载到内存中。

StreamReader class

使用@吉斯利的提示,这里是我结束了剧本:

param($file = $(Read-Host -prompt "File")) 
$fullName = (Get-Item "$file").FullName 
$sr = New-Object System.IO.StreamReader("$fullName") 
$trueCount = 0; 
$falseCount = 0; 
while (($line = $sr.ReadLine()) -ne $null) { 
     if ($line -like 'HEAD|') { continue } 
     if ($line.split("|")[4] -ge 256) { 
      $trueCount++ 
     } 
     else { 
      $falseCount++ 
     } 
} 
$sr.Dispose() 
write "True count: $trueCount" 
write "False count: $falseCount" 

它产生在大约一分钟,这符合我的性能要求同样的结果。

只需添加使用的StreamReader通过一个非常大的IIS日志文件中读取另一个例子输出所有独特的客户端的IP地址和一些PERF指标。

$path = 'A_245MB_IIS_Log_File.txt' 
$r = [IO.File]::OpenText($path) 

$clients = @{} 

while ($r.Peek() -ge 0) { 
    $line = $r.ReadLine() 

    # String processing here... 
    if (-not $line.StartsWith('#')) { 
     $split = $line.Split() 
     $client = $split[-5] 
     if (-not $clients.ContainsKey($client)){ 
      $clients.Add($client, $null) 
     } 
    } 
} 

$r.Dispose() 
$clients.Keys | Sort 

针对Get-Content小性能对比:

的StreamReader :完成5.5秒,PowerShell.exe:35328 KB RAM。

获取内容:完成23.6秒。 PowerShell.exe:1,110,524 KB RAM。