2009-05-29 88 views
2

是否有算法或diff-like工具來查找兩個csv文件之間的差異? 實施例:如何找到csv記錄的差異

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

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

利用這種差異狀公用事業它將輸出3種類型的記錄:

  1. 記錄,僅在文件1 (file1的減去file2的設定操作)
  2. 記錄存在僅存在於文件2(文件2減文件1設置操作)
  3. 在文件1和文件2中存在的記錄(相交集操作)
+0

不知道如果有一個,但只需要大約30分鐘來寫用Perl這樣的工具:) – workmad3 2009-05-29 10:57:37

回答

6

diff可以做你想做的..

diff file1.csv file2.csv --old-line-format="< %L" --new-line-format="> %L" --unchanged-line-format="= %L" 
0

您可以在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 
1

您可以使用unix'join'命令來執行此操作。它也適用於Windows的Cygwin。

例子:

$ 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 
+2

還有`comm`。 – Svante 2009-05-29 11:50:25

+0

儘管在CSV中有逗號,但兩者都會中斷。 – hbn 2009-05-29 11:53:48

0

你可以看看我的自由和開放源碼的CSV流編輯器CSVfix,它不通過你的連接命令想要的東西 - 無需編程。

0

如何使用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 
2

看看http://sourceforge.net/projects/csvdiff/

csvdiff是一個Perl腳本,DIFF /比較與 可能性來選擇分離器2個的CSV文件。差異將顯示如下: 「記錄999中的列XYZ」不同。在此之後,將顯示此列的實際和預期結果。

1

開源DiffKit是能夠做到這一點:

www.diffkit.org