Powershell将导入的CSV导出为固定记录长度且没有定界符吗?

时间:2018-07-10 12:57:01

标签: powershell csv export fixed

我有一个非常标准的CSV文件,看起来像这样:

heading1,heading2,heading3
aaaaaaaaa,bb,ccccccc
d,eeeeeeee,ff
gggggggg,hh,iiiiiiiiiii

此文件使用import-csv导入到对象。我现在想将该对象导出到具有固定记录长度,没有定界符和表头的文件中。如果导入的值对于固定文件而言太长,则应将其切除。如果导入的值太短,则这些值应保持对齐并用空格填充。

假定宽度:

heading1 is 5
heading2 is 2 
heading3 is 10

基本上,输出应如下所示:

aaaaabbccccccc   
d    eeff        
ggggghhiiiiiiiiii

请注意第3列中值末尾的空格。

算法不应完全低效-将用于转换300MB的csv文件。

我在Stackoverflow上搜索了一段时间,然后使用自定义表格格式和format-table之类的解决方案找到了一些相关的问题,但是这些解决方案似乎并不容易适应我的特定问题。

原因:专门的COTS软件需要这种非常难看/不寻常的格式。

3 个答案:

答案 0 :(得分:3)

## Q:\Test\2018\07\10\SO_51265871.ps1
$SPC = '                           ';
Import-Csv .\Input.csv | 
  ForEach-Object {"[{0}{1}{2}]" -f ($_.heading1+$SPC).Substring(0,5),
                                   ($_.heading2+$SPC).Substring(0,2),
                                   ($_.heading3+$SPC).Substring(0,10)
  } | Set-Content .\Output.rec

格式字符串中的[]仅用于显示长度,包括尾随空格。

示例输出:

PS> Get-Content .\Output.rec
[aaaaabbccccccc   ]
[d    eeff        ]
[ggggghhiiiiiiiiii]

编辑:更通用的变体,从数组中获取列宽-输出相同

$CW = @(5,2,10) # array CW = ColumnWidth
Import-Csv .\Input.csv | ForEach-Object { $i = 0
  "[{0}{1}{2}]" -f `
    ($_.heading1).PadRight($CW[$i]).Substring(0,$CW[$i++]),
    ($_.heading2).PadRight($CW[$i]).Substring(0,$CW[$i++]),
    ($_.heading3).PadRight($CW[$i]).Substring(0,$CW[$i])
  } #| Set-Content .\Output.rec

答案 1 :(得分:0)

我真的不知道你为什么要这么做,但是嘿,你这样做公平。

我想我知道您要尝试执行的操作,这将为您提供一个数组,其中每一行都将数据处理为所需的格式,然后您可以将该数组循环到txt文件,日志文件中,无论您想要什么。

$spacerCSVFile = "spacers.csv"
$prinspacerCSV = Import-Csv $spacerCSVFile -header "1","2","3"
$processedArray = New-Object System.Collections.Generic.List[System.Object]
foreach($row in $prinspacerCSV) {
    if ($row.1 -like "heading*") {
        # do nothing for headings
    } else {
        $item1 = $row.1
        $item2 = $row.2
        $item3 = $row.3

        while ($item1.length -lt 6) {
            $item1 += " "
        }
        while ($item2.length -lt 3) {
            $item2 += " "
        }
        while ($item3.length -lt 11) {
            $item3 += " "
        }
        if ($item1.length -gt 5) {
            $item1 = $item1.substring(0,5)
        }
        if ($item2.length -gt 2) {
            $item2 = $item2.substring(0,2)
        }
        if ($item3.length -gt 10) {
           $item3 = $item3.substring(0,10)
        }
        $processedArray += ,"$item1$item2$item3"
    }
}
foreach ($item in $processedArray) {
    write-host $item
}

但是我建议您值得一试,首先在此处提供一些代码,因为堆栈溢出的想法是帮助您的代码不提供它。

答案 2 :(得分:0)

这很丑陋,可能比它需要的要复杂得多,但是据我所知,这是可行的。

希望这会给您一个想法,或者只会有所帮助

$file = "C:\Logs\Test.csv"

$data = Import-Csv $file

$properties = $data | 
              Get-Member | 
              Where-Object MemberType -EQ NoteProperty | 
              Select Name

foreach ($line in $data){

    [string]$dataout = $null

    foreach ($property in $properties) {
        $dataout = $dataout + $line.($property.Name)
    }

    if($dataout.Length -eq 20){
        $dataout
    }
    elseif ($dataout.Length -lt 20) {        
        Do{
            $dataout = $dataout + " "            
        }
        Until($dataout.Length -eq 20)
        $dataout        
    }
    else {
        $dataout = ($dataout.Substring(0,20))
        $dataout        
    }
}