Unixで列別にファイルを比較する

Unixで列別にファイルを比較する

同じ行と列の数、同じレコードの順序を持​​つ2つのファイルを比較したいと思います。列の値に違いがある場合は、これを強調したいと思います。

file A:

1,kolkata,19,ab

2,delhi,89,cd

3,bangalore,56,ef

file B:

1,kolkata,21,ab

2,mumbai,89,gh

3,bangalore,11,kl

列を1主キーとみなすと、他の列と違いがあります。私はこれらの違いを強調したいと思います。

出力形式は次のとおりです(不明)。

record_number,  columns_with_diff
1               3

2               2,4

3               3,4

私の問題をdiff解決できますか?commそれでは、正確なコマンドは何ですか?

答え1

それはすべてです。各行の末尾に追加のカンマがある場合は、いくつかのスタイルの問題があります。

awk '
     BEGIN{ FS=","; ORS="" }

     { 
       # read line from secondary file
       getline aux < "file2"
       split(aux,f2,",")

       # print current line number
       print NR" "

       # process each field in current line
       for(i=1; i<=NF; i++) {
         if ($i!=f2[i]) {
           print i","
         }
       }
       print "\n"
     }
' file1

出力:

1 3,
2 2,4,
3 3,4,

答え2

以下を使用すると、これを簡単に実行できますperl

$ perl -F',' -anle '
    BEGIN{
        print "record_number,  columns_with_diff";
        $" = ",";
    }
    if (!defined($h{$.})) {
        @{$h{$.}}{0..$#F} = @F[0..$#F];
    } else {
        @diff =  grep { $h{$.}{$_} ne $F[$_] } 0..$#F;
        print "$.\t\t@{[map {$_+1} @diff]}";
    } 
    close ARGV if eof;
' file1 file2
record_number,  columns_with_diff
1       3
2       2,4
3       3,4

これを行うには、入力から空白行を削除する必要があります。

説明する

  • ブロックはBEGIN出力タイトルを印刷し、リスト区切り記号を次のように設定します。,

  • @{$h{$.}}{0..$#F} = @F[0..$#F]:ハッシュのハッシュを生成します。ここで、最初のハッシュのキーは行番号であり、各子ハッシュのキーはフィールドインデックスから1を引いた値であり、値はそのフィールドに対応する値である。

ここでは、ハッシュスライシングを使用してハッシュのハッシュに値をすばやく割り当てます。

Data::Dumperhash のハッシュを印刷すると、%h次のような内容が表示されます。

VAR1 = {
          '2' => {
                   '2' => '89',
                   '0' => '2',
                   '1' => 'delhi',
                   '3' => 'cd'
                 },
          '3' => {
                   '1' => 'bangalore',
                   '3' => 'ef',
                   '0' => '3',
                   '2' => '56'
                 },
          '1' => {
                   '3' => 'ab',
                   '1' => 'kolkata',
                   '0' => '1',
                   '2' => '19'
                 }
        };
  • %h()を作成するとif (!defined($h{$.}))(処理が完了したことを意味しますfile1)、現在の行の各フィールドをのコア値と比較して、他のすべての%hインデックスを配列に保存します@diffmap {$_+1} @diff配列インデックスは0から始まり、列番号は1から始まり、列番号を回復します。

  • close ARGV if eofカウンターを復元します$.

関連情報