2016-08-18 87 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

我做了一些更多的編輯,但這是我需要的概念!非常感謝!非常好奇。 – 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(「:」)當我跑你的代碼它仍然格式化數據跨行像數據頭,但我需要它匹配每個頭(一遍又一遍地重複在列表中)並將數據分散到行而不是行。 – user2026188

+0

對不起,你失去了我。這會將垂直排列的數據集轉換爲一組基於每個標題值的屬性的PSObjects。既然它是一個PSObject數組,你可以輸出它,但你認爲合適(如果解析器工作)。所有你需要做的是應用格式,或導出它。例如Export-Csv或Format-Table或ConvertTo-Csv。 –

+0

對不起我的錯,誤會了。我重新運行代碼並導出爲CSV。它橫向發送它,但是標題不匹配,所以它只是水平重複而不是垂直重複。 – user2026188