2013-02-10 2 views
2

у меня есть Notepad ++, PowerShell, и Excel 2007. У меня есть два CSV-файлы с именем database.csv и import.csv , Import.csv содержит новые записи, которые я хочу поместить в мою базу данных онлайн. Database.csv содержит текущие записи в этой базе данных. Оба файла содержат простой список уникальных значений с разделителями-новинками.Удалить строки, присутствующие в одном .csv из другого .csv (Windows, PowerShell, Notepad ++)

Однако база данных может содержать некоторые записи в новом файле. И новый файл содержит записи, отсутствующие в базе данных. И файл базы данных содержит записей, которые все еще сохраняются для целей записи, но не находятся во входном файле.

Простое объединение результатов приводит к дублированию любой записи, имеющей постоянное существование. Это также приводит к одиночным копиям записей, которые присутствуют только в базе данных и записываются только , присутствующие во входном файле.

Что я хочу - это файл, содержащий только записи, которые присутствуют только во входном файле. Любые советы?

+0

делать вам какие-либо столбцы, которые делают строку уникальным в файле? Я бы? первый + фамилия? –

ответ

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. ИМХО.

+0

, если вы ищете производительность на больших файлах, вы должны избегать 'get-content' all together =) –

+0

Я думаю, что это зависит от приложения и от того, как вы используете Get-Content. Сравните [IO.File] :: ReadAllLines с Get-Content -ReadCount 0. – mjolinor

+0

ofc, но для больших файлов get-content медленный, период. –

3

Если предположить, что ваши CSV-файлы имеют столбцы а, Ь, & с:

$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 

Просто заменить, б и с именами столбцов, которые вы хотите сравнить

+0

Это не работает должным образом с csv-объектами (по крайней мере для меня). Кроме того, это вернет «новые» строки из '$ db' тоже, что он не хочет –

+1

@Graimer: вы правы, я не тестировал его, это было из памяти. Я только что обновил свой ответ с проверенным решением. – KevinD

0

Compare-Object борьбу иногда с customobject, импортированным из 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 
Смежные вопросы