合并两个 CSV 文件
Merge two CSV files
我想将两个 header 相同的 CSV 文件合并为一个 CSV 文件。
我有两个这样的文件,如下所示,即 DevData.csv
和 ProdData.csv
具有相同的 cfname
和不同的 ID
s
ID cfname
-------------------- -----------------------------------
10201 Risk ID
10202 Issue ID
10203 Dependency ID
10204 Server ID
10205 Parent Application ID
10206 Application Service ID
10207 Application Supportability
10208 Application Compatibility
10300 Application Status
10301 Contact ID Type 2
10302 Contact ID Type 3
10303 Contact ID Type 4
10304 Business Service Manager
10308 Server Location Name:
10309 Rack Position:
10310 Rack Number:
10311 Data Centre
10312 Server Group
(14 rows affected)
我想创建以下格式的新 CSV:
DevID ProdID cfname
-------------------- ------ -----------------------------------
10201 201 Risk ID
10202 202 Issue ID
10203 203 Dependency ID
10204 204 Server ID
10205 205 Parent Application ID
10206 206 Application Service ID
10207 207 Application Supportability
10208 208 Application Compatibility
10300 209 Application Status
10301 210 Contact ID Type 2
10302 211 Contact ID Type 3
10303 212 Contact ID Type 4
10304 213 Business Service Manager
10308 214 Server Location Name:
以下是我当前的代码,但它导出第一个文件的数据,并在其下方导出下一个文件的数据。
function Merge-CSVFiles {
[cmdletbinding()]
param(
[string[]]$CSVFiles
)
$Output = @();
foreach ($CSV in $CSVFiles) {
if (Test-Path $CSV) {
$FileName = [System.IO.Path]::GetFileName($CSV)
$temp = Import-CSV -Path $CSV |
select ID, cfname, ID, cfname, @{Expression={$FileName}}
$Output += $temp
} else {
Write-Warning "$CSV : No such file found"
}
}
$Output | Export-Csv -Path $OutputFile -NoTypeInformation
Write-Output "$OutputFile successfully created"
}
Merge-CSVFiles -CSVFiles "C:\Users\ECSAdmin\Desktop\Proddata.csv", "C:\Users\ECSAdmin\Desktop\Devdata.csv" -OutputFile "C:\Users\ECSAdmin\Desktop\Mergedata.csv"
你可以对两个集合做一个嵌套的foreach循环,但是两个避免执行时间相对于输入大小呈指数增长,更好的策略是加载一个集合进入哈希表(使用公共 属性 cfname
作为键)然后遍历另一个并将两个连接起来:
$DevData = @'
ID,cfname
10201,Risk ID
10202,Issue ID
10203,Dependency ID
10204,Server ID
10205,Parent Application ID
10206,Application Service ID
10207,Application Supportability
10208,Application Compatibility
10300,Application Status
10301,Contact ID Type 2
10302,Contact ID Type 3
10303,Contact ID Type 4
10304,Business Service Manager
10308,Server Location Name:
10309,Rack Position:
10310,Rack Number:
10311,Data Centre
10312,Server Group
'@ |ConvertFrom-Csv
$ProdData = @'
ID,cfname
201,Risk ID
202,Issue ID
203,Dependency ID
204,Server ID
205,Parent Application ID
206,Application Service ID
207,Application Supportability
208,Application Compatibility
209,Application Status
210,Contact ID Type 2
211,Contact ID Type 3
212,Contact ID Type 4
213,Business Service Manager
214,Server Location Name:
'@ |ConvertFrom-Csv
# throw one set into a hashtable
# we can use this as a lookup table for the other set
$ProdTable = @{}
foreach($line in $ProdData){
$ProdTable[$line.cfname] = $line.ID
}
# Output the DevData with the appropriate ProdData value
$DevData |Select-Object @{Label='DevID';Expression={$_.ID}},@{Label='ProdID';Expression={$ProdTable[$_.cfname]}},cfname |Export-Csv .\new.csv -NoTypeInformation
您可以试试这个简单的命令管道:
Out-file -FilePath '.\csv3.csv' -InputObject "ProdID,ID,cfname"; ForEach($CFName In $Csv1) { $Csv2.Where({$_.cfname -eq $CFName.cfname}) | %{ "$($_.ProdID),$($CFName.ID),$($_.cfName)" } | Out-File .\csv3.csv -Append}
我假设 Csv1.csv 是第一个包含 ID 和 cfname 列的文件,第二个文件 Csv2.csv 包含 ProdID 和 cfname 列。这将生成第三个文件 csv3.csv,其中包含合并的内容
由于您使用 sqlcmd
从 SQL 服务器导出数据,因此您需要添加参数 -W
和 -s","
让您的命令创建实际的 CSV 输出:
sqlcmd -S server -d db -E -Q "query" -W -s"," -o output.csv
一旦您有了实际的 CSV 文件,您就可以像这样处理它们:
# create a hashtable from the second CSV, so you can look up IDs by the
# values in the "cfname" column
$proddata = @{}
Import-Csv 'C:\path\to\ProdData.csv' | ForEach-Object {
$proddata[$_.cfname] = $_.ID
}
Import-Csv 'C:\path\to\DevData.csv' |
Select-Object @{n='DevID';e={$_.ID}},
@{n='ProdID';e={$proddata[$_.cfname}}, cfname |
Export-Csv 'C:\path\to\merged.csv'
这确实假定您的 ProdData.csv
仅包含 cfname
也出现在 DevData.csv
中的值,并且您的 cfname
值至少在 ProdData.csv
中是唯一的].双向合并更复杂,因为您需要检查 $proddata
中的 whick keys 在 DevData.csv
中不存在并相应地附加它们。如果您的 cfname
值不是唯一的,您将无法对齐记录。
我想将两个 header 相同的 CSV 文件合并为一个 CSV 文件。
我有两个这样的文件,如下所示,即 DevData.csv
和 ProdData.csv
具有相同的 cfname
和不同的 ID
s
ID cfname -------------------- ----------------------------------- 10201 Risk ID 10202 Issue ID 10203 Dependency ID 10204 Server ID 10205 Parent Application ID 10206 Application Service ID 10207 Application Supportability 10208 Application Compatibility 10300 Application Status 10301 Contact ID Type 2 10302 Contact ID Type 3 10303 Contact ID Type 4 10304 Business Service Manager 10308 Server Location Name: 10309 Rack Position: 10310 Rack Number: 10311 Data Centre 10312 Server Group (14 rows affected)
我想创建以下格式的新 CSV:
DevID ProdID cfname -------------------- ------ ----------------------------------- 10201 201 Risk ID 10202 202 Issue ID 10203 203 Dependency ID 10204 204 Server ID 10205 205 Parent Application ID 10206 206 Application Service ID 10207 207 Application Supportability 10208 208 Application Compatibility 10300 209 Application Status 10301 210 Contact ID Type 2 10302 211 Contact ID Type 3 10303 212 Contact ID Type 4 10304 213 Business Service Manager 10308 214 Server Location Name:
以下是我当前的代码,但它导出第一个文件的数据,并在其下方导出下一个文件的数据。
function Merge-CSVFiles {
[cmdletbinding()]
param(
[string[]]$CSVFiles
)
$Output = @();
foreach ($CSV in $CSVFiles) {
if (Test-Path $CSV) {
$FileName = [System.IO.Path]::GetFileName($CSV)
$temp = Import-CSV -Path $CSV |
select ID, cfname, ID, cfname, @{Expression={$FileName}}
$Output += $temp
} else {
Write-Warning "$CSV : No such file found"
}
}
$Output | Export-Csv -Path $OutputFile -NoTypeInformation
Write-Output "$OutputFile successfully created"
}
Merge-CSVFiles -CSVFiles "C:\Users\ECSAdmin\Desktop\Proddata.csv", "C:\Users\ECSAdmin\Desktop\Devdata.csv" -OutputFile "C:\Users\ECSAdmin\Desktop\Mergedata.csv"
你可以对两个集合做一个嵌套的foreach循环,但是两个避免执行时间相对于输入大小呈指数增长,更好的策略是加载一个集合进入哈希表(使用公共 属性 cfname
作为键)然后遍历另一个并将两个连接起来:
$DevData = @'
ID,cfname
10201,Risk ID
10202,Issue ID
10203,Dependency ID
10204,Server ID
10205,Parent Application ID
10206,Application Service ID
10207,Application Supportability
10208,Application Compatibility
10300,Application Status
10301,Contact ID Type 2
10302,Contact ID Type 3
10303,Contact ID Type 4
10304,Business Service Manager
10308,Server Location Name:
10309,Rack Position:
10310,Rack Number:
10311,Data Centre
10312,Server Group
'@ |ConvertFrom-Csv
$ProdData = @'
ID,cfname
201,Risk ID
202,Issue ID
203,Dependency ID
204,Server ID
205,Parent Application ID
206,Application Service ID
207,Application Supportability
208,Application Compatibility
209,Application Status
210,Contact ID Type 2
211,Contact ID Type 3
212,Contact ID Type 4
213,Business Service Manager
214,Server Location Name:
'@ |ConvertFrom-Csv
# throw one set into a hashtable
# we can use this as a lookup table for the other set
$ProdTable = @{}
foreach($line in $ProdData){
$ProdTable[$line.cfname] = $line.ID
}
# Output the DevData with the appropriate ProdData value
$DevData |Select-Object @{Label='DevID';Expression={$_.ID}},@{Label='ProdID';Expression={$ProdTable[$_.cfname]}},cfname |Export-Csv .\new.csv -NoTypeInformation
您可以试试这个简单的命令管道:
Out-file -FilePath '.\csv3.csv' -InputObject "ProdID,ID,cfname"; ForEach($CFName In $Csv1) { $Csv2.Where({$_.cfname -eq $CFName.cfname}) | %{ "$($_.ProdID),$($CFName.ID),$($_.cfName)" } | Out-File .\csv3.csv -Append}
我假设 Csv1.csv 是第一个包含 ID 和 cfname 列的文件,第二个文件 Csv2.csv 包含 ProdID 和 cfname 列。这将生成第三个文件 csv3.csv,其中包含合并的内容
由于您使用 sqlcmd
从 SQL 服务器导出数据,因此您需要添加参数 -W
和 -s","
让您的命令创建实际的 CSV 输出:
sqlcmd -S server -d db -E -Q "query" -W -s"," -o output.csv
一旦您有了实际的 CSV 文件,您就可以像这样处理它们:
# create a hashtable from the second CSV, so you can look up IDs by the
# values in the "cfname" column
$proddata = @{}
Import-Csv 'C:\path\to\ProdData.csv' | ForEach-Object {
$proddata[$_.cfname] = $_.ID
}
Import-Csv 'C:\path\to\DevData.csv' |
Select-Object @{n='DevID';e={$_.ID}},
@{n='ProdID';e={$proddata[$_.cfname}}, cfname |
Export-Csv 'C:\path\to\merged.csv'
这确实假定您的 ProdData.csv
仅包含 cfname
也出现在 DevData.csv
中的值,并且您的 cfname
值至少在 ProdData.csv
中是唯一的].双向合并更复杂,因为您需要检查 $proddata
中的 whick keys 在 DevData.csv
中不存在并相应地附加它们。如果您的 cfname
值不是唯一的,您将无法对齐记录。