web-dev-qa-db-ja.com

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で問題を解決できますか?はいの場合、正確なコマンドは何でしょうか?

4
user2910372

これだろう。各行の終わりに余分なコンマがあるスタイルの問題。

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,
3
LatinSuD

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::Dumper_を使用してハッシュのハッシュ_%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_の対応する値と比較し、すべての配列_@diff_で異なるインデックス。 _map {$_+1} @diff_配列のインデックスは0から始まり、列番号は1から始まるため、列番号を復元します。

  • _close ARGV if eof_復元_$._カウンター。

1
cuonglm