2016-08-18 3 views
0

Ich habe einen Powershell-Code geschrieben, um eine sehr große .txt-Datei zu lesen, bestimmte Zeilen auszuwählen und sie in eine CSV-Datei einzufügen. das Problem ist, dass die Datei wie folgt formatiert ist:Konvertieren von Textdateien in CSV-Dateien

header1: Data1 
header2: Data1 
header3: Data1 
header4: Data1 
header1: Data2 
header2: Data2 
header3: Data2 
header4: Data2 

und ich brauche es dazu zu konvertieren:

Header1,Header2,Header3,Header4 
data1,data1,data1,data1 
data2,data2,data2,data2 

der Code ist dies:

$path = get-location 
    $textfile = Get-FileName $env:USERPROFILE\Downloads\ 


    $writefile = "$path\data2.csv" 
    $reader = [System.IO.File]::OpenText($textfile) 
    $writer = New-Object System.IO.StreamWriter $writefile 
    $writer.WriteLine('{0},{1},{2},{3}', "Policy","Schedule Type","Retention Level","Host") 

     for(;;) { 

       $line = $reader.ReadLine() # 
       if ($null -eq $line) { 
       break 
       } 

       $data = $line.Split(":") 

       if ($null -ne $data[0]) { 
       $newdata0 = $data[0].trimstart(" ") 
       } 
       if ($null -ne $data[1]) { 
       $newdata1 = $data[1].trimstart(" ") 
       } 

       if ($newdata0 -eq "Policy") {$writer.WriteLine('{0},{1},{2},{3}', $newdata1,$null,$null,$null)} 

       if ($newdata0 -eq "Schedule Type") {$writer.WriteLine('{0},{1},{2},{3}', $null,$newdata1,$null,$null)} 

       if ($newdata0 -eq "Retention Level") {$writer.WriteLine('{0},{1},{2},{3}', $null,$null,$newdata1,$null)} 

       if ($newdata0 -eq "Host") {$writer.WriteLine('{0},{1},{2},{3}', $null,$null,$null,$newdata1)}  

      } 



    $reader.Close() 
    $writer.Close() 

aber ich am Ende mit diesem (tatsächliche Daten):

Policy,Schedule Type,Retention Level,Host 
FS-Win-Servers-Tokyo-DACS_ONLY,,, 
,FULL (0),, 
,,infinity (9), 
,,,opback03e.options-it.com 
DB-Win-Exch2013-ADB11,,, 
,INCR (1),, 
,,6 months (6), 
,,,opback03e.options-it.com 
DB-Win-Exch2013-MDB11,,, 
,INCR (1),, 
,,6 months (6), 
,,,opback03e.options-it.com 
DB-Win-Exch2013-MDB10,,, 
,INCR (1),, 
,,6 months (6), 
,,,opback03e.options-it.com 

Ich denke, dass ich über diesen Code falsch bin oder vielleicht nur einen Weg finden muss, um den CSV neu zu formatieren?

+0

ich denke, das wird Ihnen helfen: http://stackoverflow.com/a/8970351/5341953 – notgiorgi

+0

Dank aber Ich habe die CSV-Datei. Das Problem ist in meinem Code, ich kann die Daten nicht auf eine Zeile der CSV schreiben. Es schreibt in die richtige Spalte, aber ich weiß, wie man die Daten in derselben Zeile bekommt. – user2026188

Antwort

0

Ihr Problem ist jeder Aufruf von $ writer.WriteLine wird die Zeile in der Zieldatei voran, die Sie gerade schreiben. Sie benötigen die Informationen auf jeder Schleife zu sammeln, aber nur einmal schreiben jede vierte Schleife, dies funktionieren könnte:

$loopCounter = 0 

    for(;;) { 

      $line = $reader.ReadLine() # 
      if ($null -eq $line) { 
      break 
      } 

      $data = $line.Split(":") 

      if ($null -ne $data[0]) { 
      $newdata0 = $data[0].trimstart(" ") 
      } 
      if ($null -ne $data[1]) { 
      $newdata1 = $data[1].trimstart(" ") 
      } 

      if ($newdata0 -eq "Policy") {$data1=$newdata} 

      if ($newdata0 -eq "Schedule Type") {$data2=$newdata} 

      if ($newdata0 -eq "Retention Level") {$data3=$newdata} 

      if ($newdata0 -eq "Host") {$data4=$newdata}  


      if (($loopCounter % 4) -eq 3) {$writer.WriteLine('{0},{1},{2},{3}', $data1, $data2, $data3, $data4)}   

      $loopCounter++ 

     } 
+0

ive habe etwas mehr bearbeitet, aber das ist das Konzept, das ich brauchte! vielen Dank! sehr geschätzt. – user2026188

0

Ich würde geneigt sein, etwas zu machen, das nach Wiederholung sucht, um als ein Rekordtrennzeichen zu wirken (das Ende der Linie ersetzend).

$header = New-Object System.Collections.Generic.List[String] 
Get-Content test.txt | Where-Object { $_ -match '(?<Header>[^:]+): *(?<Value>.+)$' } | ForEach-Object { 
    if ($header.Contains($matches.Header)) { 
     # End of record start again. 
     $header.Clear() 
     # Output 
     $psObject 
    } 
    if ($header.Count -eq 0) { 
     # Start of the record. Create an object to hold it. 
     $psObject = New-Object PSObject 
    } 

    # Add the current header and value to the object. 
    $psObject | Add-Member $matches.Header $matches.Value 
    # Add the header name to the record controller 
    $header.Add($matches.Header)  
} 
# Output the last entry from the file (no end detection) 
$psObject 
+0

hi Ja, ich habe das mit $ data = $ line.Split (":") gemacht, wenn ich deinen Code ausgeführt habe, formatiert er die Daten immer noch über Zeilen wie header: data, aber ich brauche es für jeden Header (die sich immer wiederholen) in der Liste) und verteilen Sie die Daten über Zeilen statt Zeilen. – user2026188

+0

Entschuldigung, du hast mich verloren. Dies verwandelt Ihren vertikal angeordneten Datensatz in eine Menge von PSObjects, deren Eigenschaften auf jedem der Headerwerte basieren. Da es sich um ein Array von PSObject handelt, können Sie es ausgeben, wie Sie es für richtig halten (wenn der Parser funktioniert). Alles, was Sie tun müssen, ist ein Format anzuwenden oder zu exportieren. z.B. 'Export-Csv' oder' Format-Tabelle' oder 'ConvertTo-Csv'. –

+0

Entschuldigung, meine Schuld, falsch verstanden. Ich habe den Code erneut ausgeführt und in CSV exportiert. Die Header werden jedoch nicht horizontal ausgerichtet, sondern nur horizontal und nicht vertikal. – user2026188