2016-12-02 28 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循環中,您仍然可以按照原樣拆分字符串,如果需要,請執行操作,然後將其寫出。沒有必要積累它,等待最後完成。

這種方法應該更快,應該幾乎不使用任何內存。