将多个 csv 文件合并为一个的 Powershell 脚本
Powershell script to combine multiple csv files to single one
我在 C:\temp 中有 3 个 csv 文件。尝试将所有 3 个 csv 文件合并为单个文件。
F1.csv
、F2.csv
、F3.csv
[都具有唯一的 headers 和不同的行数和列数]。以下是文件中的示例内容。
F1.csv
F1C1 F1C2
ABC 123
F2.csv
F2C1 F2C2
DEF 456
GHI 789
JKL 101112
F3.csv
F3C1
MNO
PQR
我希望结果 csv 文件 FR.csv 如下所示 FR.csv
F1C1 F1C2 F2C1 F2C2 F3C1
ABC 123 DEF 456 MNO
GHI 789 PQR
JKL 101112
我试过 运行 下面的脚本,但是 FR.csv
在单列中给出了输出。
Get-Content C:\temp\*csv | Add-Content C:\temp\FinalResult.csv
以下解决方案假定 Get-ChildItem *.csv
按所需顺序枚举要合并的文件(适用于输入文件 F1.csv
、F2.csv
、F3.csv
当前目录)。
Plain-text解决方案,使用.NET API,System.IO.StreamReader
and System.IO.StreamWriter
:
此解决方案比下面的 OO 解决方案执行得更好,但后者为您提供更大的灵活性。没有 Unicode BOM 的输入文件被假定为 UTF-8 编码,输出保存到当前目录中名为 FR.csv
的 BOM-less UTF8 文件。 (如果需要,所使用的 API 允许您指定不同的编码)。
$outFile = 'FR.csv'
# IMPORTANT: Always use *full* paths with .NET APIs.
# Writer for the output file.
$writer = [System.IO.StreamWriter] (Join-Path $Pwd.ProviderPath $outFile)
# Readers for all input files.
$readers = [System.IO.StreamReader[]] (Get-ChildItem *.csv -Exclude $outFile).FullName
# Read all files in batches of corresponding lines, join the
# lines of each batch with ",", and save to the output file.
$isHeader = $true
while ($readers.EndOfStream -contains $false) {
if ($isHeader) {
$headerLines = $readers.ReadLine()
$colCounts = $headerLines.ForEach({ ($_ -split ',').Count })
$writer.WriteLine($headerLines -join ',')
$isHeader = $false
} else {
$i = 0
$lines = $readers.ForEach({
if ($line = $_.ReadLine()) { $line }
else { ',' * ($colCounts[$i] - 1) }
++$i
})
$writer.WriteLine($lines -join ',')
}
}
$writer.Close()
$readers.Close()
OO解决方案,使用Import-Csv
and ConvertTo-Csv
/ Export-Csv
:
# Read all CSV files into an array of object arrays.
$objectsPerCsv =
Get-ChildItem *.csv -Exclude FR.csv |
ForEach-Object {
, @(Import-Csv $_.FullName)
}
# Determine the max. row count.
$maxCount = [Linq.Enumerable]::Max($objectsPerCsv.ForEach('Count'))
# Get all column names per CSV.
$colNamesPerCsv = $objectsPerCsv.ForEach({ , $_[0].psobject.Properties.Name })
0..($maxCount-1) | ForEach-Object {
$combinedProps = [ordered] @{}
$row = $_; $col = 0
$objectsPerCsv.ForEach({
if ($object = $_[$row]) {
foreach ($prop in $object.psobject.Properties) {
$combinedProps.Add($prop.Name, $prop.Value)
}
}
else {
foreach ($colName in $colNamesPerCsv[$col]) {
$combinedProps.Add($colName, $null)
}
}
++$col
})
[pscustomobject] $combinedProps
} | ConvertTo-Csv
将ConvertTo-Csv
替换为Export-Csv
以将数据导出到文件;根据需要使用 -NoTypeInformation
参数和 -Encoding
;例如... | Export-Csv -NoTypeInformation -Encoding utf8 Merged.csv