使用PowerShell进行文本文件处理 - 性能问题

时间:2016-12-02 16:55:21

标签: performance powershell

我使用下面的PowerShell脚本来读取和处理一个17 MB的文本文件。输入文件包含大约200 000行和12列。目前,该脚本需要将近1个小时来处理输入文件。如何优化处理时间?

脚本:

$fields = Get-Content Temp.txt
$results = @()
foreach($i in $fields)
{
     $field   = $i -split '\t' -replace '^\s*|\s*$'
     $field1  = $field[0]
     $field2  = $field[1]
     $field3  = $field[2]
     $field4  = $field[3]
     $field5  = $field[4]
     $field6  = $field[5]
     $field7  = $field[6]
     $field8  = $field[7]
     $field9  = $field[8]
     $field10 = $field[9]
     $field11 = $field[10]
     $field12 = $field[11]

     if ($field1 -eq "4803" -and $field[2].substring(0,2) -eq "60")
     {
         $field2 = "5000000"
     }
     else
     {
         $field2 = $field[1]
     }
     $details = @{       
                Column1  = $field1
                Column2  = $field2
                Column3  = $field3
                Column4  = $field4
                Column5  = $field5
                Column6  = $field6
                Column7  = $field7
                Column8  = $field8
                Column9  = $field9
                Column10 = $field10
                Column11 = $field11
                Column12 = $field12
            }
    $results += New-Object PSObject -Property $details 
    }
$results | ForEach-Object { '{0}    {1} ... {11}' -f $_.Column1,$_. Column1,... $_.Column12 } | Set-Content -path Temp.txt
[Environment]::Exit(0)

2 个答案:

答案 0 :(得分:2)

除非我在这里遗漏了一些东西,否则目标是接收制表符分隔的数据,根据另一个字段修改一个字段,然后输出为CSV数据,是否正确?如果是这样,这个单行应该更快地执行。

<img alt="alt text" src="path/to-image.png" /><img alt="alt text" src="path/to-image.png" /><img alt="alt text" src="path/to-image.png" /><img alt="alt text" src="path/to-image.png" />

它避免了所有奇怪的字符串解析并解决了最大的问题

Import-Csv test.txt -Header @(1..12) -Delimiter `t | % {if(($($_.2) -eq "4803") -and($($_.3).substring(0,2) -eq "60")){$_.2 = "5000000"};$_} | export-csv test2.csv -NoTypeInformation

该行将整个数组复制到脚本的每一行的新数组中,这对性能有问题。其余的变化只会让事情变得更快。

答案 1 :(得分:0)

如果这是我,如果您的文件变得更大,我会开始考虑不使用Get-Content。内存消耗将开始成为一个问题,如果您的文件变得非常大,使用Get-Content将无法很好地扩展,因为您将所有内容都拉入内存。并且记住它将比文件的大小更多的内存,因为它必须将事物表示为对象(它仍然比XML DOM小,但无论如何,它需要内存)。

首先,你可以使用流阅读器循环输入文件,我在这里有一个例子:https://stackoverflow.com/a/32337282/380016

你也可以使用流编写器编写输出文件,而不是像你一样连接一个大对象,只是循环遍历它并在最后将它写入文件。

在我的示例的while循环中,您仍然可以按原样拆分字符串,如果需要,可以进行操作,然后将其写出来。无需累积它并等待最后完成所有操作。

这种方法应该更快,几乎不能使用任何内存。