我想比较具有相同行数和列数且记录顺序相同的两个文件。只是想突出显示列值中的差异(如果有)。
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
,将所有不同的索引存储在数组中@diff
。map {$_+1} @diff
恢复列号,因为数组索引从0开始,列号从1开始。close ARGV if eof
恢复$.
计数器。