Слияние двух файлов CSV

-5

Я хочу объединить два CSV файла, которые имеют один и тот же заголовок в один файл CSV. У меня есть два таких файла, как показано ниже: DevData.csv и ProdData.csv с тем же cfname и другим ID

    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"

спросил(а) 2021-01-19T18:41:41+03:00 9 месяцев, 1 неделя назад
1
Решение
79

Вы можете сделать вложенный цикл foreach над двумя наборами, но два избежать времени выполнения, экспоненциально возрастающего относительно размера ввода, лучшей стратегией было бы загрузить один набор в cfname (используя общее свойство 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

ответил(а) 2021-01-19T18:41:41+03:00 9 месяцев, 1 неделя назад
47

Поскольку вы экспортируете данные с SQL Server с помощью sqlcmd вам нужно добавить параметры -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. Два слияния -W ay более сложны, так как вам нужно проверить, что ключи whick в $proddata не существуют в DevData.csv и соответственно добавить их. Если ваши значения cfname не уникальны, вы не сможете выровнять записи.

ответил(а) 2021-01-19T18:41:41+03:00 9 месяцев, 1 неделя назад
46

Вы можете попробовать этот простой конвейер команд:

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 с объединенным содержимым

ответил(а) 2021-01-19T18:41:41+03:00 9 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема