2014-09-02 69 views
0

有兩個CSV文件我想比較。但是,它們具有不同的順序的標題和行/值。如何按標頭對CSV文件進行排序?

這裏有一個簡單的例子:

INPUT FILE1:

NAME,AGE,BDAY 
ABC,1,090214 
DEF,1,122514 

INPUT FILE2:

BDAY,NAME,AGE 
122514,DEF,1 
090214,ABC,1 

INPUT FILE3:

BDAY,NAME,AGE 
122514,DEFG,1 
090214,ABC,1 

DIFF FILE1和FILE2

No diffs. 

DIFF FILE1和FILE3

Found diffs in FILE and FILE3. 

<Any format of diffs is okay.> 

我可以輕鬆地創建一個perl腳本,但我這樣做之前,沒有人知道,如果有現有的腳本/工具已經做到了這一點?

我曾嘗試將文件從UNIX複製到Windows,並使用Excel對它們進行排序。它運行良好,但我遇到保存問題。

我也有google搜索,但找不到這個參考。

感謝您的任何輸入。

+0

這是一個有點不清楚你問:如何重新排序?如何排序?表明您希望的輸出清楚。提示:'awk'可以通過切換列來完成工作。 – fedorqui 2014-09-02 07:38:41

+0

您可以使用AWK對列進行重新排序,但您需要指定'cat file1 | awk -F',''BEGIN {OFS =「,」;} {print $ 3,$ 1,$ 2}'' – 2014-09-02 07:46:40

+0

@ChrisDoyle是的,好點。但請注意,不需要'cat':'awk'BEGIN {FS = OFS =「,」} {print ...}'file'。 – fedorqui 2014-09-02 07:48:02

回答

2

我認爲你需要某種先進的比較(需要更深入的分析),所以使用關係數據庫方法可能很有趣。 在這方面,module DBD::CSV是有幫助的。它允許寫入SELECT語句,包括表之間的連接。

+0

酷!從來不知道存在CSV文件的DBI驅動程序! – Carlisle18 2014-09-02 10:54:28

0

規範化數據

  1. 使用Text::CSV重新排序CSV文件的列。
  2. 然後,您可以使用Perl ’的s sort或其他一些實用程序重新排序文件的行。

這也採用Text::Wrap在一個可喜的格式顯示標準化文件:

use strict; 
use warnings; 
use autodie; 

# Setup fake data 
my @files; 
{ 
    local $/ = ''; # Paragraph mode 
    while (<DATA>) { 
     chomp; 
     my ($file, $data) = split "\n", $_, 2; 
     open my $fh, '>', $file; 
     print $fh $data, "\n"; 
     push @files, $file; 
    } 
} 

# Normalize Files by Column Order 
use Text::CSV; 

my $csv = Text::CSV->new({ binary => 1, eol => $/ }) 
    or die "Cannot use CSV: " . Text::CSV->error_diag(); 

for my $file (@files) { 
    local @ARGV = $file; 
    local $^I = '.bak'; 
    my @old_order; 
    my @new_order; 
    while (<>) { 
     if (!$csv->parse($_)) { 
      die "Bad parse $file, line $.: " . $csv->error_diag(); 
     } 

     my @columns = $csv->fields(); 

     if ($. == 1) { 
      @old_order = @columns; 
      @new_order = sort @columns; 
     } 

     my %hash; 
     @hash{@old_order} = @columns; 

     if (!$csv->combine(@hash{@new_order})) { 
      die "Bad combine $file, line $.: " . $csv->error_diag(); 
     } 

     print $csv->string(); 
    } 
    unlink "$file$^I"; # Optionally delete backup 
} 

# Normalize Files by Row Order 
for my $file (@files) { 
    my ($header, @data) = do { local @ARGV = $file; <> }; 
    open my $fh, '>', $file; 
    print $fh $header, sort @data; 
} 

# View Normalized Files 
use Text::Wrap; 
for my $file (@files) { 
    open my $fh, '<', $file; 
    print wrap(sprintf("%-12s", $file), ' ' x 12, <$fh>,), "\n"; 
} 

__DATA__ 
file1.csv 
NAME,AGE,BDAY 
ABC,1,090214 
DEF,1,122514 

file2.csv 
BDAY,NAME,AGE 
122514,DEF,1 
090214,ABC,1 

file3.csv 
BDAY,NAME,AGE 
122514,DEFG,1 
090214,ABC,1 

輸出:

file1.csv AGE,BDAY,NAME 
      1,090214,ABC 
      1,122514,DEF 

file2.csv AGE,BDAY,NAME 
      1,090214,ABC 
      1,122514,DEF 

file3.csv AGE,BDAY,NAME 
      1,090214,ABC 
      1,122514,DEFG 
相關問題