我有notepad ++,powershell和excel 2007.我有两个名为.csv的文件 database.csv 和 import.csv 。 Import.csv包含我想要添加的新条目 进入我的数据库在线。 Database.csv包含该数据库中的当前记录。 这两个文件都包含一个简单的逗号换行分隔的唯一值列表。
但是,数据库可能已在新文件中包含一些条目。而且,新的 file包含不在数据库中的条目。并且,数据库文件包含 仍为录制目的而保留但不在输入文件中的条目。
简单地将它们组合在一起会导致任何记录存在重复。 它还导致仅存在于数据库和记录中的单个记录副本 出现在输入文件中。
我想要的是一个只包含仅存在于输入文件中的记录的文件。 有什么建议吗?
答案 0 :(得分:3)
假设您的csv文件包含列a,b和& C:
$db = Import-Csv database.csv
$import = Import-Csv import.csv
$new = Compare-Object -ReferenceObject $db -DifferenceObject $import -Property a,b,c -PassThru | ? { $_.SideIndicator -eq "=>" } | Select a,b,c
只需将a,b和c替换为您要比较的列的名称
答案 1 :(得分:2)
Powershell的:
Get-Content <database file> -TotalCount 1 |
Set-Content C:\somedir\ToUpload.csv
$import = @{}
Get-Content <import file> |
select -Skip 1
foreach {
$import[$_] = $true
}
Get-Content <Database file> |
select -Skip 1 |
foreach {
if ($import[$_])
{
$import[$_].remove()
}
}
$import.Keys |
Add-Content C:\Somedir\ToUpload.csv
或者,将两个文件都读入内存:
Get-Content <database file> -TotalCount 1 |
Set-Content C:\somedir\ToUpload.csv
$import = Get-Content <import file>
select -Skip 1
$database = Get-Content <database file>
select -Skip 1
$import |
where {$database -notcontains $_} |
Add-Content C:\somedir\ToUpload.csv
使用导入/导出csv的解决方案可以正常工作,但与将文件作为文本数据处理相比,会产生额外的内存和进程开销。差异可能很小或很大,具体取决于文件的大小和csv文件中的列数。 IMHO。
答案 2 :(得分:0)
Compare-Object
有时会与从csv导入的customobject发生争执。
如果你想要性能(对于大型csv文件),你可以试试这个:
$i = @{}
[IO.File]::ReadAllLines("C:\input.csv") | % { $i[$_] = $true }
$reader = New-Object System.IO.StreamReader "C:\db.csv"
#Skip header. This way the output file(new.csv) will get input.csv's header
$reader.ReadLine() | Out-Null
while (($line = $reader.ReadLine()) -ne $null) {
#Remove row if it exists in db.csv
if ($i.ContainsKey($line)) {
$i.Remove($line)
}
}
$reader.Close()
$i.Keys | Add-Content c:\new.csv