【问题标题】:Powershell export an imported CSV as fixed record length with no delimiter?Powershell将导入的CSV导出为没有分隔符的固定记录长度?
【发布时间】:2018-12-18 08:05:50
【问题描述】:

我有一个非常标准的 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 上搜索并搜索了一段时间,并且可以使用自定义表格格式和格式表格等解决方案找到一些相关问题,但这些解决方案似乎不太适合我来解决这个特定问题。

至于原因:小众 COTS 软件需要这种非常丑陋/不寻常的格式。

【问题讨论】:

  • 出于好奇,你打算如何处理这种奇怪的输出?
  • 你写过什么吗?
  • 我建议查看格式化字符串'{0,20}' -f 'Foo'
  • @EBGreen:是的,我已经写了一点,正如提到的一些带有一些管道、选择、重新排列等的 import-csv。)我实际上考虑过将其添加到我的问题中。但是,我决定不将其包含在问题中,因为它只会使问题更长,而不会添加任何其他信息。
  • 添加您尝试过的信息,特别是您尝试过的代码会做三件事(至少对我而言)。有时问题涉及我不熟悉的系统。我知道 Powershell,但您可能正在使用一些我不熟悉的模块。查看您的代码可以让我们以适合您情况的方式回答。另一个考虑是,经常看到代码会指出问题的某些方面,而这些方面在问题的普通语言版本中并不清楚。最后,它会告诉我们您的知识水平,以便我们更好地回答

标签: powershell csv export fixed


【解决方案1】:
## 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

【讨论】:

  • 我还没有尝试过,但这看起来很干净,并非完全低效且可读。将尽快尝试并提供反馈。
  • 确实,这很好用。谢谢。我接受这个作为答案,除非出现更好/更快的东西。但是,您可能希望在第二个版本中取消注释 Set-Content 位。
【解决方案2】:

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

我想我抓住了你想要做的事情,这会给你一个数组,每一行都是将数据处理成你想要的格式,然后你可以将该数组循环到一个 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
}

不过,我建议值得一试,并首先准备好一些代码,因为堆栈溢出的想法是帮助您的代码不提供它。

【讨论】:

    【解决方案3】:

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

    希望这能给你一个想法或者这只是帮助

    $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        
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多