Как найти разницу в записи CSV - PullRequest
2 голосов
/ 29 мая 2009

Есть ли алгоритм или утилиты, похожие на diff, чтобы найти разницу между двумя CSV-файлами? Пример:

file1
-------
key1,value1
key2,value2
key3,value3
key5,value5
key7,value7

file2
-------
key1,value1
key3,value3
key4,value4
key5,value5
key6,value6

С помощью этих утилит, похожих на diff, будет выводиться 3 типа записей:

  1. Записи, которые существуют только в файле1 (file1 минус file2 операция установки)
  2. Записи, которые существуют только в файле2 (файл2 минус операция набора файлов1)
  3. Записи, которые существуют как в файле1, так и в файле2 (операция пересечения множества)

Ответы [ 8 ]

6 голосов
/ 29 мая 2009

diff может делать то, что вы хотите ..

diff file1.csv file2.csv --old-line-format="< %L" --new-line-format="> %L" --unchanged-line-format="= %L"
2 голосов
/ 23 июля 2010

Взгляните на http://sourceforge.net/projects/csvdiff/

csvdiff - это Perl-скрипт для сравнения / сравнения двух CSV-файлов с Возможность выбора разделителя. Различия будут показаны как: «Колонка XYZ в записи 999» отличается. После этого фактическое и ожидаемый результат для этого столбца будет показан.

2 голосов
/ 29 мая 2009
1 голос
/ 15 декабря 2010

Открытый исходный код DiffKit может сделать это:

www.diffkit.org

1 голос
/ 29 мая 2009

Вы можете использовать команду unix 'join', чтобы сделать это. Он также доступен в Cygwin для Windows.

Пример:

$ join -t ',' -v 1 file1 file2
key2,value2
key7,value7
$ join -t ',' -v 2 file1 file2
key4,value4
key6,value6
$ join -t ',' file1 file2
key1,value1,value1
key3,value3,value3
key5,value5,value5
0 голосов
/ 29 мая 2009

Как насчет примера использования SQLite ?

DROP TABLE 'file1';
DROP TABLE 'file2';

CREATE TABLE 'file1' (
    key_field VARCHAR primary key,
    value_field VARCHAR
);

CREATE TABLE 'file2' (
    key_field VARCHAR primary key,
    value field VARCHAR
);


.bail off
.separator ,
.import file1.csv file1
.import file2.csv file2

.output stdout
.header on

SELECT col1 AS 'In file1.csv, not in file2.csv' FROM (
    SELECT file1.key_field AS col1,
           file2.key_field AS col2 
    FROM file1 LEFT OUTER JOIN file2
    ON file1.key_field == file2.key_field
) 
WHERE col2 IS NULL
;

SELECT col2 AS 'In file2.csv, not in file1.csv'FROM (
    SELECT file1.key_field AS col1,
           file2.key_field AS col2
    FROM file2 LEFT OUTER JOIN file1
    ON file2.key_field == file1.key_field
) WHERE col1 IS NULL
;

SELECT file1.key_field AS 'In both file1.csv and file2.csv'
    FROM file1 INNER JOIN file2
    WHERE file1.key_field == file2.key_field
;

Вот вывод:

C:\Temp> sqlite3 test.db < t.sql
In file1.csv, not in file2.csv
key2
key7
In file2.csv, not in file1.csv
key4
key6
In both file1.csv and file2.csv
key1
key3
key5
0 голосов
/ 29 мая 2009

Вы можете взглянуть на мой редактор потоков FOSS CSV CSVfix , который делает то, что вы хотите, с помощью команды соединения - программирование не требуется.

0 голосов
/ 29 мая 2009

Вы можете использовать хеши в Perl. Читайте каждый файл в отдельный хеш, что-то вроде

my %File1 = ();
my %File2 = ();
# Filehandles FP1 and FP2 is opened for read
while (<FP1>) {
    if (/^([^,]+),(.+)$/) {
        my ($key, $value) = ($1, $2);
        $File1{$key} = $value;
    }
}
# Repeat for FP2

Чтобы распечатать результаты, вы можете пройтись по хэшам и проверить, идентичны ли ключ / значение, различны или отсутствуют по-разному. Пример:

for my $key (keys %File1) {
    if (defined($File1{$key}) && defined($File2{$key}) {
        print("$key exists in both files\n");
    } elsif (defined($File1{$key})) {
        print("$key exists only in file1\n");
    }
}
# Repeat for %File2
...