2016-12-02 3 views
0

Ich verwende Powershell-Skript unten, um eine 17 MB Textdatei zu lesen und zu verarbeiten. Die Eingabedatei enthält ca. 200 000 Zeilen und 12 Spalten. Derzeit benötigt das Skript fast eine Stunde, um die Eingabedatei zu verarbeiten. Wie kann ich die Bearbeitungszeit optimieren?Textdateiverarbeitung mit Powershell - Leistungsproblem

Script:

$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

Nun, warum fängst du nicht damit an, das als CSV zu importieren? auch die 'else'-Bedingung ist redundant. Können Sie eine geeignete Datei zum Testen bereitstellen? Sie können alle Informationen mit etwas ersetzen – 4c74356b41

+0

Ich habe mit Import-CSV auch getestet. Ich stehe vor denselben Problemen. Es läuft für 1 Stunde. Aber es dauert nur 20 Sekunden für die Verarbeitung von 10000 Datensätzen. – AravindhK

+0

Duplikat von [https://social.technet.microsoft.com/Forums/scriptcenter/en-US/c5bdc740-837a-43f6-97d5-b0f0d5bf22bc/](https://social.technet.microsoft.com/Forums/ scriptcenter/de-DE/c5bdc740-837a-43f6-97d5-b0f0d5bf22bc /). StackOverflow ist auch kein kostenloser Redesign-Dienst. –

Antwort

2

Es sei denn, ich bin etwas fehlt hier das Ziel in Tabulator getrennte Daten zu nehmen ist, modifizieren ein Feld auf eine andere Basis, und dann als CSV-Daten, korrekt ausgibt? Wenn ja, sollte dieser One-Liner viel schneller ausführen.

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 

Es vermeidet die ganze seltsame Zeichenfolgenanalyse und wird um das größte Problem, das Ihre

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

Diese Zeile für jede Zeile des Skripts in ein neues Array gesamte Array zu kopieren ist, die ist problematisch für die Leistung. Der Rest der Änderungen macht die Dinge nur etwas schneller.

+0

Ich frage mich, ob die einfache Änderung '$ Ergebnisse' in' Arraylist' würde die Leistung verbessern – 4c74356b41

+0

Es könnte aber AFAIK es würde immer noch die Kopie für jede Zeile der Datei benötigen (ich habe das nicht getestet und könnte falsch sein), Sie könnten die Leistung verbessern, indem Sie $ forecies = * foreach loop * setzen und dann die $ results + = inside loswerden Die Schleife, die die ganze Sache ohne irgendwelche Kopien zuweisen würde, aber es ist immer noch eine Menge Code, um zu erreichen, was ein paar Zeilen ohne Probleme schafft. –

+0

Einer der großen Vorteile dieses Vorschlags besteht darin, dass die Daten gepumpt werden, anstatt dass die gesamte große Datei gleichzeitig eingelesen werden muss. – lit

0

Wenn ich das wäre, würde ich anfangen über Get-Content nachzudenken, wenn Ihre Dateien viel größer werden. Speicherverbrauch wird zu einem Problem werden, und die Verwendung von Get-Content wird nicht gut skalieren, wenn Ihre Dateien wirklich groß werden, weil Sie alles in den Speicher ziehen. Und denken Sie daran, dass es mehr Speicher als die Dateigröße geben wird, da es Objekte als Objekte darstellen muss (was immer noch kleiner ist als ein XML-DOM, aber unabhängig davon, benötigt es Speicher).

Also zunächst einmal, Sie könnten Schleife durch die Eingabedatei eines Stream-Reader, habe ich hier ein Beispiel: https://stackoverflow.com/a/32337282/380016

Sie können auch Ihre Ausgabedatei mit dem Datenstrom-Schreiber schreiben, anstatt ein großes Objekt von concatting wie du bist, nur durchschlinge es und schreibe es am Ende in eine Datei.

In der While-Schleife meines Beispiels können Sie die Zeichenfolge noch teilen, wie Sie sind, wenn Sie möchten, tun Sie Ihre Manipulationen, und schreiben Sie es dann aus. Keine Notwendigkeit, es zu sammeln und warten Sie, um alles am Ende zu tun.

Dieser Ansatz sollte schneller sein und sollte kaum Speicher verwenden.