2009-05-05 62 views
2

定期接收我們無法控制的外部來源的CSV文件。這些文件是當前記錄的完整集合;但是,自上次以來刪除的任何記錄都不存在。我們想比較這兩個文件並創建一個單獨的已刪除記錄文件,以便我們可以對它們進行一些額外的處理。在另一個領域的應用程序中,我們有一個商業分類包(CoSort),它可以實現這一功能;然而,我們在這裏沒有訪問權限。儘管如此,這些數量並不是那麼大,看起來這是標準或免費工具可能很容易處理的事情。理想情況下,這將採用Windows批處理文件的形式,但Perl或awk解決方案也可以。例如輸入文件:在Windows中,如何比較兩個文件並僅返回第一個文件中原來存在的第二個文件中缺少的記錄?

上一個文件:

X_KEY,X_NAME,X_ATTRIBUTE 
123,Name 123,ATT X 
111,Name 111,ATT X 
777,Name 777,ATT Y 

傳入的文件:

X_KEY,X_NAME,X_ATTRIBUTE 
777,Name 777,ATT Y 
123,Name 123,ATT CHANGED 

生成的文件應至少包括:

111,Name 111 

但是,如果被刪除的屬性記錄也通過,這很好。

到目前爲止,我有一個使用免費軟件CMSort兩個文件減去頭記錄進行排序的批處理文件,以使其更容易爲某些類型的DIFF過程:

REM Sort Previous File, Skip Header 

C:\Software\CMSort\cmsort.exe /H=1 x_previous.txt x_previous_sorted.txt 

REM Sort Incoming File, Skip Header 

G:\Software\CMSort\cmsort.exe /H=1 x_incoming.txt x_incoming_sorted.txt 

但「比較,只有展示從第一個文件丟失的記錄'位是逃避我。複雜性的一部分是許多屬性可以在剩下的記錄中改變,所以它不是純粹的差異。然而,它感覺就像是一個專門的diff命令 - 它只限於檢查關鍵字段,而不是整個記錄。不過,我似乎無法得到正確的語法。想法?記錄數不應超過5萬條記錄。

注意:如果這是SQL並且數據位於表中,我們可以使用EXCEPT operator,但在這種情況下將數據移到數據庫不是一個選項。

+2

既然你提到差異,這是值得注意的是,diffutils的是可用於Windows : http://gnuwin32.sourc eforge.net/packages/diffutils.htm – si28719e 2009-05-05 23:54:33

回答

2

,如果我是這樣做在Perl中我只用一對夫婦的哈希,


#!/usr/bin/perl -w                           
use strict; 
use warnings; 

my %orig; my %new; my %changed; 

open(F1,"<$ARGV[0]")||die"Couldn't open $ARGV[0]: $!\n"; 
while(<F1>){ 
    chomp; 
    @_ = split(/,/); 
    $orig{$_[0]} = $_; 
} 
close(F1); 

open(F2,"<$ARGV[1]")||die"Couldn't open $ARGV[1]: $!\n"; 
while(<F2>){ 
    chomp; 
    @_ = split(/,/); 
    if($orig{$_[0]}){ 
     if($orig{$_[0]} ne $_){ 
      $changed{$_[0]} = $orig{$_[0]}."||".$_; 
     } 
     delete $orig{$_[0]}; 
    }else{ 
     $new{$_[0]} = $_; 
    } 
} 
close(F2); 

print "Deleted:\n"; 
print map{$orig{$_}."\n"} sort {$b<=>$a} keys %orig; 
print "Added:\n"; 
print map{$new{$_}."\n"} sort {$b<=>$a} keys %new; 
print "Changed:\n"; 
print map{$changed{$_}."\n"} sort {$b<=>$a} keys %changed; 

假設你的文字的例子是在文件f1.txt和f2.txt,


kettle$ ./compare.pl f1.txt f2.txt 

Deleted: 
111,Name 111,ATT X 
Added: 
Changed: 
123,Name 123,ATT X||123,Name 123,ATT CHANGED 

0

編寫一個經過第一個文件的小控制檯應用程序並解析出鍵並檢查第二個文件中與鍵匹配的行並創建第三個文件並不困難。我想我說這似乎是一個很好的情況下推出自己的。 :)順便說一句,這是一個O(mn)操作,其中m,n是文件1和文件2的大小,所以它可能不會很快。

1
#!/usr/bin/perl 

use strict; 
use warnings; 

@ARGV == 2 or die "mycompare oldfile newfile\n"; 

my ($oldfile, $newfile) = @ARGV; 

my %newrecords; 

open my $new, '<', $newfile 
    or die "Cannot open '$newfile':$!"; 

scalar <$new>; # skip header 

while (my $line = <$new>) { 
    next unless $line =~ /\S/; 
    my ($record) = split /,/, $line; 
    $newrecords{ $record } = 1; 
} 

close $new; 

open my $old, '<', $oldfile 
    or die "Cannot open '$oldfile': $!"; 

scalar <$old>; # skip header 

while (my $line = <$old>) { 
    next unless $line =~ /\S/; 
    my ($record) = split /,/, $line; 
    print $line unless exists $newrecords{ $record }; 
} 

close $new; 

__END__ 

C:Temp> mycompare old.csv new.csv 
111,Name 111,ATT X 
0

我會使用diff,如果它不能直接使用,請通過cygwin使用它。

0

我以前在很長一段時間的工作依稀相似的系統上一次(令人不安的接近20年前,其實)。數據存儲在數據庫中,並且傳入的數據必須與前一週的數據進行比較。數據中有74列數據,其中一些採用'prev code,prev date'對(幾個週期)的形式。所以,一個合法的組更改是爲:

Old: 
name1: value1  date1: 2000-01-01 
name2: value2  date2: 1995-05-31 
name3: value3  date3: 1990-10-13 

New: 
name1: New Name  date1: 2009-03-31 
name2: Other Name date2: 2005-04-12 
name3: value1  date3: 2000-01-01 

在這種情況下,究竟是什麼「名1,DATE1」已經成爲「NAME3,DATE3」;在過去某個時間似乎出現了中間名稱變更,並且最近名稱發生了變化。關於名稱變化的情報可能會延遲。弄清楚之前發生的事情以及全新的事情是非常艱難的。事實上,整個過程很棘手。

我實際上開發了一個雙語自我再生程序來管理這些東西。源代碼的頂部利用了主要語言(Informix 4GL)中的註釋符號,它使用了shell風格的#... eol註釋和{...}註釋(後者能夠遍佈多行。當然,這也是一個用於I/O重定向的shell構造,所以我有了一個shell腳本,它將生成嵌入在{...}註釋中的I4GL代碼,並且該代碼是從定義70 +柱和如何每一個需要進行處理。這節省了很多時間打字。 ^ h

相關問題