2016-12-02 70 views
0

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

脚本:

$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) 
+0

好吧,你为什么不开始导入这个作为csv? “else”条件也是多余的。你能提供适当的文件进行测试吗?你可以用一些东西替换所有的信息 – 4c74356b41

+0

我也用import-csv进行了测试。我面临同样的问题。它运行1小时。但处理10000条记录只需要20秒。 – AravindhK

+0

重复[https://social.technet.microsoft.com/Forums/scriptcenter/en-US/c5bdc740-837a-43f6-97d5-b0f0d5bf22bc/](https://social.technet.microsoft.com/Forums/脚本中心/ EN-US/c5bdc740-837a-43f6-97d5-b0f0d5bf22bc /)。 StackOverflow也不是免费的代码重新设计服务。 –

回答

2

除非我失去了一些东西在这里的目标是把在制表符分隔的数据,修改基于另一个字段,然后输出为CSV数据,是否正确?如果是这样的话,这个单线程应该执行得更快。

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 

这就避免了所有的怪异的字符串解析并围绕这是

$results += New-Object PSObject -Property $details

这条线正在复制整个数组到一个新的数组脚本的每一行,最大的问题得到哪些对性能有问题。其余的改变只是让事情稍微快一点。

+0

我不知道如果简单地将'$ results'改为'Arraylist'会提高性能很多 – 4c74356b41

+0

它可能但AFAIK它仍然需要该文件的每一行的副本(我没有测试过这个,可能是错误的),你可以通过设置$ results = * foreach循环来提高性能,然后去掉$ results + = inside循环,这将分配整个事情W/O做任何副本,但它仍然是一大堆代码来完成几行管理没有麻烦。 –

+0

这个建议的一大好处就是它可以管理数据,而不需要一次读入整个大文件。 – lit

0

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

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

您也可以使用流作家,而不是concatting一个大对象写入输出文件像你一样,只是循环通过它,并写在最后的文件。

在我的例子的while循环中,您仍然可以按照原样拆分字符串,如果需要,请执行操作,然后将其写出。没有必要积累它,等待最后完成。

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