使用PowerShell合并两个CSV文件时SAMAccountName列为空问题求解
问题原因
原脚本存在3处核心逻辑错误,才会导致SAMAccountName列空值:
- Compare-Object的匹配逻辑完全错误:你要匹配的是CSV2的
Mail列和CSV1的对应列,但原脚本强行匹配不存在的CSV2的SAMAccountName属性,永远找不到匹配结果 - 错误读取匹配结果属性:Compare-Object返回的匹配项是CSV1的行对象,不存在
.value属性,需要直接取.SAMAccountName属性 - 错误的变量赋值逻辑:Add-Member默认会直接修改原对象,不需要重新赋值给
$Record,临时变量的赋值不会同步到原$csv2数组中
修正后的PowerShell脚本
这里给两种实现,数据量小用第一种,数据量超过1000条推荐用第二种哈希表查找的方案,效率更高:
基础修正版
$csv1 = Import-Csv -Path C:\TEMP\CSV1.csv $csv2 = Import-Csv -Path C:\temp\CSV2.csv ForEach($Record in $csv2){ # 匹配逻辑:CSV2的Mail等于CSV1的mail,取对应的SAMAccountName # 如果你确实是要CSV2的Mail等于CSV1的SAMAccountName,把下面的$_.mail改成$_.SAMAccountName即可 $matchedItem = $csv1 | Where-Object { $_.mail -eq $Record.Mail } | Select-Object -First 1 $null = Add-Member -InputObject $Record -Type NoteProperty -Name "SAMAccountName" -Value $matchedItem.SAMAccountName -Force } $csv2 | Export-Csv 'C:\temp\merged.csv' -NoTypeInformation -Encoding UTF8
高效哈希表版(推荐)
# 先把CSV1转成哈希表,键为mail,值为SAMAccountName,查找效率提升数十倍 $csv1Map = @{} Import-Csv -Path C:\TEMP\CSV1.csv | ForEach-Object { # 同样如果匹配键是SAMAccountName就改成$_.SAMAccountName $csv1Map[$_.mail] = $_.SAMAccountName } $csv2 = Import-Csv -Path C:\temp\CSV2.csv ForEach($Record in $csv2){ $samAccountName = $csv1Map.ContainsKey($Record.Mail) ? $csv1Map[$Record.Mail] : $null $null = Add-Member -InputObject $Record -Type NoteProperty -Name "SAMAccountName" -Value $samAccountName -Force } $csv2 | Export-Csv 'C:\temp\merged.csv' -NoTypeInformation -Encoding UTF8
补充说明
- 如果你的匹配逻辑确实是「CSV2的Mail列值等于CSV1的SAMAccountName列值」,只要把脚本注释处提到的匹配键替换即可
- 增加了
-Encoding UTF8参数避免导出中文乱码,不需要可以删掉 - 增加了
-Force参数,重复运行脚本不会报错
内容的提问来源于stack exchange,提问作者denprash
相关产品推荐
相关产品推荐

