我正在使用Invoke-RestMethod以CSV格式从供应商处获取数据。数据不是我需要的格式(需要发送给另一个供应商) - 每个列有四列" set",可以有任意数量的"设置"在CSV中 - 列标题名称不是静态的 - 每四列是一个完整的集合。
Column1a,Column2a,Column3a,Column4a,Column1z,Column2z,Column3z,Column4z </ p>
数据,数据,数据,数据,数据,数据,数据
我需要做的是导出1-4,5-8,9-12等列以分离CSV。我甚至不知道从哪里开始。
答案 0 :(得分:5)
尝试这样的事情:
$csv = Import-Csv 'input.csv'
$headers = $csv[0].PSObject.Properties | select -Expand Name
$step = 4
for ($i = 0; $i -lt $headers.Count; $i += $step) {
$csv | select $headers[$i..($i+$step-1)] |
Export-Csv "output_$($i/$step).csv" -NoType
}
Import-Csv
从输入文件创建对象列表,其中CSV列名称成为对象属性名称。因此,您可以通过展开对象的属性名称从对象中提取标题名称。使用每个输出文件要导出的列数的步长迭代标题数组,并使用范围运算符(..
)选择要在当前迭代中导出的列。
答案 1 :(得分:1)
拥有样本数据会很好但我认为解决方案的要点不需要它。使用您的列我创建了4列分组数据。第一组包含字母,第二组包含数字。最后,它们将位于单独的文件中。
Column1a, Column2a, Column3a, Column4a, Column1z, Column2z, Column3z, Column4z
A,B,C,D,1,2,3,4
A,B,C,D,1,2,3,4
A,B,C,D,1,2,3,4
A,B,C,D,1,2,3,4
A,B,C,D,1,2,3,4
A,B,C,D,1,2,3,4
所以我并不关心数据是如何到达的,因此我在我的示例中使用Get-Content
导入数据,以获得原始csv数据,这可能是您从Invoke-RestMethod
获得的。现在,我们通过将第一行排除到$header
来获取该数据中的列,假设列名在第一行中。如果不是,如果它是第二行,您可以使用Select -Index 2
。 旁注我以为我可以从Get-Member
得到它,但是它按字母顺序排列,所以虽然Ansgar Wiechers的答案处理的比我的清洁,但它已被废弃了。
在我们标题之后,我们将数据转换为对象以供进一步处理。神奇来自循环,它以4列组的形式导航对象。 警告:我假设您的列数为4的倍数,以便完美运行。
对于输出,只需取我们当前在$groupHeaders
中的4列,然后加入一个字符串。特殊字符可以搞砸那一个。使用一点正则表达式轻松解决问题。
$outputPath = "C:\temp\"
$data = GC C:\temp\null.csv
#$header = $data | gm -MemberType NoteProperty | Select-Object -ExpandProperty Name
$header = ($data | select -first 1).split(",") | ForEach-Object{$_.Trim()}
$data = $data | ConvertFrom-Csv
$specialCharactersRegex = [regex]::Escape('"*/:<>?\|')
For($group = 1;$group -le ($header.Count / 4);$group++){
$headerStartIndex = ($group - 1) * 4
$groupHeaders = $header[$headerStartIndex..($headerStartIndex+3)]
$data | Select @($groupHeaders) | Export-CSV "$outputPath$(($groupHeaders -join '') -replace $specialCharactersRegex).csv" -NoTypeInformation
}
最后,我有两个文件,其中包含各自列的数据。
Column1aColumn2aColumn3aColumn4a.csv
Column1zColumn2zColumn3zColumn4z.csv