在unix中按列比较文件

在unix中按列比较文件

我想比较具有相同行数和列数且记录顺序相同的两个文件。只是想突出显示列值中的差异(如果有)。

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::Dumper打印 hash of hashes %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恢复$.计数器。

相关内容