2016-08-18 3 views
0

Я написал код powershell, чтобы прочитать очень большой файл .txt, выбрать определенные строки и поместить их в CSV. проблема заключается в том, что файл отформатирован так:преобразование текстового файла в CSV-файл

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

и мне нужно, чтобы преобразовать его в этом:

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

код это:

$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() 

, но я в конечном итоге с этим (фактические данные):

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 

Я думаю, что я ошибаюсь в этом коде или, может быть, просто нужно найти способ переформатировать CSV?

+0

Я думаю, что это поможет вам: http://stackoverflow.com/a/8970351/5341953 – notgiorgi

+0

спасибо, но У меня есть файл CSV. проблема в моем коде, я не могу заставить данные писать на одной строке CSV. он записывает в правильный столбец, но я знаю, как получить данные в одной строке. – user2026188

ответ

0

Ваша проблема заключается в каждом вызове $ writer.WriteLine продвигается строку в файл назначения, который вы пишете. Вы должны собрать информацию о каждом цикле, но писать только один раз каждый 4-й цикл, это может работать:

$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 сделал еще несколько изменений, но это та концепция, которая мне нужна! Огромное спасибо! очень приветствуется. – user2026188

0

Я был бы склонен сделать что-то для повторения, чтобы действовать как разделитель записей (заменяя конец строки).

$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

привет, я делал это с $ data = $ line.Split (":"), когда я запускал ваш код, он все еще форматирует данные по строкам, такие как header: data, но мне нужно, чтобы он соответствовал каждому заголовку (который повторяется снова и снова вниз по списку) и распространять данные по строкам вместо строк. – user2026188

+0

Извините, вы потеряли меня. Это превратит ваш вертикально упорядоченный набор данных в набор объектов PSO, которые имеют свойства, основанные на каждом из значений заголовка. Поскольку это массив PSObject, вы можете выводить его, но вы считаете нужным (если работал парсер). Все, что вам нужно сделать, это применить формат или экспортировать его. например 'Export-Csv' или' Format-Table' или 'ConvertTo-Csv'. –

+0

извините, моя вина, неправильно понята. Я перезапустил код и экспортировал его в CSV. который отправляет его по горизонтали, однако заголовки не сопоставляются, поэтому они просто повторяются горизонтально, а не вертикально. – user2026188