Convert fixed width txt file to CSV / set-content or out-file -append?

前端 未结 3 1181
长情又很酷
长情又很酷 2020-12-18 11:22

Input file is a fixed-width txt file. My client normally opens it in Excel and manually specifies the column breaks. I\'m hoping to replace certain blank spaces with a comma

相关标签:
3条回答
  • 2020-12-18 12:00

    Here is the working code. Fixed few bugs.

    CD 'C:\\FOLDERPATH\'
    $filter = "FILE_NAME_*.txt" 
    
    $columns = 11,22,32,42,54 
    
    # DO NOT NEED TO REVERSE [array]::Reverse($columns) #too lazy to re-write array after finding out I need to iterate in reverse
    
    $files = get-childitem ./ |where-object {$_.Name -like $filter}
    $newDelimiter = '|'
    
    foreach($file in $files)
    {
        $file
    
        $csvFile = 'C:\\FOLDERPATH\NEW_' + $file.BaseName + '.txt'
        if (!(get-childitem ./ |where-object {$_.Name -like $csvFile})) #check whether file has been processed
        { 
    
            $content | ForEach {
                $line = $_
                $counter = 0
                $columns | ForEach {
                    $line = $line.Insert($_+$counter, $newDelimiter)  
                    $counter = $counter + 1
                    }
                $line = $line.Trim($newDelimiter)
                $line
            } | set-content $csvFile
        }
    
    } 
    
    0 讨论(0)
  • 2020-12-18 12:14

    I would think this comes up a lot. Here's an example that actually goes overboard and turns the fixed width file into objects. Then it's simple to export that to a csv. This should work for converting legacy commands like netstat as well.

    $cols = 0,19,38,59,81,97,120,123 # fake extra column at the end, assumes all rows are that wide, padded with spaces
    $colsfile = 'columns.txt'
    $csvfile = 'cust.csv'
    
    $firstline = get-content $colsfile | select -first 1
    $headers = for ($i = 0; $i -lt $cols.count - 1; $i++) {
      $firstline.substring($cols[$i], $cols[$i+1]-$cols[$i]).trim()
    }
    
    # string Substring(int startIndex, int length)                                                                                         
    
    Get-Content $colsfile | select -skip 1 | ForEach {
      $hash = [ordered]@{}
      for ($i = 0; $i -lt $headers.length; $i++) {
        $value = $_.substring($cols[$i], $cols[$i+1]-$cols[$i]).trim()
        $hash += @{$headers[$i] = $value}
      }
      [pscustomobject]$hash
    } | export-csv $csvfile
    
    0 讨论(0)
  • 2020-12-18 12:24

    Set-Content should work fine with some minor adjustments. Here is an example of how it should work (this is everything within your outer foreach loop):

    $csvFile = $file.BaseName
        if (!(get-childitem ./ |where-object {$_.Name -like $csvFile})) #check whether file has been processed
        { 
            (gc $file | foreach {
                    $_.Insert($columBreaks[0],",").Insert($columBreaks[1],",").Insert($columBreaks[2],",").`
                    Insert($columBreaks[3],",").Insert($columBreaks[4],",").Insert($columBreaks[5],",").`
                    Insert($columBreaks[6],",").Insert($columBreaks[7],",").Insert($columBreaks[8],",").`
                    Insert($columBreaks[9],",").Insert($columBreaks[10],",")
                }) | set-content $csvFile #note parenthesis around everything that gets piped to set-content
        }
    

    By the way, instead of splitting the filename on the '.', you can just get the name without the extension by using $file.BaseName:

    $csvFile = $file.BaseName + ".csv"
    
    0 讨论(0)
提交回复
热议问题