2

我有 notepad++、powershell 和 excel 2007。我有两个名为 database.csvimport.csv的 .csv 文件。Import.csv 包含我想在线放入我的数据库的新条目。Database.csv 包含该数据库中的当前记录。这两个文件都包含一个简单的逗号换行符分隔的唯一值列表。

但是,数据库可能已经包含新文件中的一些条目。并且,新文件包含不在数据库中的条目。并且,数据库文件包含仍保留用于记录目的但不在输入文件中的条目。

简单地将它们组合起来会导致任何持续存在的记录的重复。它还导致仅存在于数据库中的记录的单个副本和仅存在于输入文件中的记录。

我想要的是一个仅包含仅存在于输入文件中的记录的文件。有什么建议吗?

4

3 回答 3

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 替换为您要比较的列的名称

于 2013-02-11T04:52:47.583 回答
2

电源外壳:

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 文件中的列数。恕我直言。

于 2013-02-11T00:36:24.063 回答
0

Compare-Object如果您没有任何要匹配的特定属性,有时会遇到从 csv 导入的自定义对象。

如果你想要性能(对于大型 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
于 2013-02-11T08:12:10.777 回答