我使用下面的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)
答案 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循环中,您仍然可以按原样拆分字符串,如果需要,可以进行操作,然后将其写出来。无需累积它并等待最后完成所有操作。
这种方法应该更快,几乎不能使用任何内存。