我有两个包含数据的csv文件,我需要检查CSV 2中是否存在CSV 1中的值,如果是,则用file1中的数据替换file2中的该值,如果没有,则跳到另一行,>
File1.csv
NO;Description
L001;DREAM
L002;CAR
L003;PHONE
L004;HOUSE
L005;PLANE
File2.csv
ID;Name;Status*;Scheduled Start Date;Actual Start Date;Actual End Date;Scheduled End Date;SLA
144862;DREAM;Scheduled;1524031200;;;1524033000;
149137;CAR;Implementation In Progress;1528588800;;;1548968400;
150564;PHONE;Scheduled;1569456000;;;1569542400;
150564;HOUSE;Scheduled;1569456000;;;1569542400;
150564;PLANE;;;;;;
我尝试了类似的方法,但是它对我不起作用:
$file1 = Import-Csv "C:\Users\file1.csv" |Select-Object -ExpandProperty Description
$file2 = Import-Csv "C:\Users\file1.csv" |Select-Object -ExpandProperty NO
Import-Csv "C:\Users\file3.csv" |Where-Object {$file1 -like $_.Name} |ForEach-Object {
$_.Name = $file2($_.NO)
} |Out-File "C:\Users\File4.csv"
File4.csv应该这样:
ID;Name;Status*;Scheduled Start Date;Actual Start Date;Actual End Date;Scheduled End Date;SLA
144862;L001;Scheduled;1524031200;;;1524033000;
149137;L002;Implementation In Progress;1528588800;;;1548968400;
150564;L003;Scheduled;1569456000;;;1569542400;
150564;L004;Scheduled;1569456000;;;1569542400;
150564;L005;;;;;;
也许还有另一种方法可以实现我的目标!谢谢
答案 0 :(得分:0)
这是您可以采用的一种方法:
Import-Csv
导入两个CSV文件Description
是键,而NO
是值。Name
列中的所有值(如果键存在)。我们可以使用System.Collections.Hashtable.ContainsKey
来检查密钥是否存在。这是恒定时间的O(1)
操作,因此查找速度很快。 Export-Csv
导出最终的CSV。我使用-UseQuotes Never
在您的输出文件中没有引号"
。此功能仅在 PowerShell 7 中可用。对于较低的PowerShell版本,可以查看How to remove all quotations mark in the csv file using powershell script?,以了解从CSV文件中删除引号的其他替代方法。 演示:
$csvFile1 = Import-Csv -Path .\File1.csv -Delimiter ";"
$csvFile2 = Import-Csv -Path .\File2.csv -Delimiter ";"
$ht = @{}
foreach ($item in $csvFile1) {
if (-not [string]::IsNullOrEmpty($item.Description)) {
$ht[$item.Description] = $item.NO
}
}
& {
foreach ($line in $csvFile2) {
if ($ht.ContainsKey($line.Name)) {
$line.Name = $ht[$line.Name]
}
$line
}
} | Export-Csv -Path File4.csv -Delimiter ";" -NoTypeInformation -UseQuotes Never
我们可以使用Call Operator &
,而不是使用Foreach-Object
将foreach
循环包装在脚本块中。您可以查看about_script_blocks
,以获取有关脚本块的更多信息。
$csvFile2 | ForEach-Object {
if ($ht.ContainsKey($_.Name)) {
$_.Name = $ht[$_.Name]
}
$_
} | Export-Csv -Path File4.csv -Delimiter ";" -NoTypeInformation -UseQuotes Never
File4.csv
ID;Name;Status*;Scheduled Start Date;Actual Start Date;Actual End Date;Scheduled End Date;SLA
144862;L001;Scheduled;1524031200;;;1524033000;
149137;L002;Implementation In Progress;1528588800;;;1548968400;
150564;L003;Scheduled;1569456000;;;1569542400;
150564;L004;Scheduled;1569456000;;;1569542400;
150564;L005;;;;;;
更新
要使用相同的Name
处理多个值,我们可以将上面的内容转换为使用System.Management.Automation.PSCustomObject
的哈希表,其中我们有两个属性Count
来跟踪当前项我们看到的是NO
,它是一个数字数组:
$csvFile1 = Import-Csv -Path .\File1.csv -Delimiter ";"
$csvFile2 = Import-Csv -Path .\File2.csv -Delimiter ";"
$ht = @{}
foreach ($row in $csvFile1) {
if (-not $ht.ContainsKey($row.Description) -and
-not [string]::IsNullOrEmpty($item.Description)) {
$ht[$row.Description] = [PSCustomObject]@{
Count = 0
NO = @()
}
}
$ht[$row.Description].NO += $row.NO
}
& {
foreach ($line in $csvFile2) {
if ($ht.ContainsKey($line.Name)) {
$name = $line.Name
$pos = $ht[$name].Count
$line.Name = $ht[$name].NO[$pos]
$ht[$name].Count += 1
}
$line
}
} | Export-Csv -Path File4.csv -Delimiter ";" -NoTypeInformation -UseQuotes Never
答案 1 :(得分:0)
如果文件不太大,则可以通过简单的ForEach-Object循环来实现:
$csv1 = Import-Csv -Path 'D:\Test\File1.csv' -Delimiter ';'
$result = Import-Csv -Path 'D:\Test\File2.csv' -Delimiter ';' |
ForEach-Object {
$name = $_.Name
$item = $csv1 | Where-Object { $_.Description -eq $name } | Select-Object -First 1
# update the Name property and output the item
if ($item) {
$_.Name = $item.NO
# if you output the row here, the result wil NOT contain rows that did not match
# $_
}
# if on the other hand, you would like to retain the items that didn't match unaltered,
# then output the current row here
$_
}
# output on screen
$result | Format-Table -AutoSize
#output to new CSV file
$result | Export-Csv -Path 'D:\Test\File4.csv' -Delimiter ';' -NoTypeInformation
屏幕结果:
ID Name Status* Scheduled Start Date Actual Start Date Actual End Date Scheduled End Date SLA -- ---- ------- -------------------- ----------------- --------------- ------------------ --- 144862 L001 Scheduled 1524031200 1524033000 149137 L002 Implementation In Progress 1528588800 1548968400 150564 L003 Scheduled 1569456000 1569542400 150564 L004 Scheduled 1569456000 1569542400 150564 L005