我有两个文件
File1
Row Col1 Col2 Col3 Col4
1 A B C D
2 E F G H
File2
Row Col1 Col2 Col3 Col4
1 A Z C D
2 E F Y H
3 M N O P
要求是逐行,然后逐列比较。使用这两个输出文件需要创建。 首先是来自file2的第3行,它指出这些行在file2中是新的。 第二个文件将具有此输出:
FileName Row ColName ColValue
File1 1 Col2 B (--this is old value)
File2 1 Col2 Z (--this is new value)
File1 2 Col3 G
File2 2 Col3 Y
现在获取file1中缺少但在file2中存在的行可以通过
完成awk 'NR==FNR{a[$1]++;next;}!($0 in a)' file2 file1
但不确定如何生成第二个输出文件。
答案 0 :(得分:1)
完成规范:
答案将忽略“删除的记录”问题。
问题是观察到这个逻辑找到了在File2中插入的记录:
awk 'NR==FNR{a[$1]++;next;}!($0 in a)' file2 file1
接近正确;它应该是!($1 in a)
。需要显式打印才能将输出发送到文件。对于其余的逻辑,我们可以非常容易地发现字段中的变化:
awk 'NR == FNR { a[$1] = $0; next }
!($1 in a) { print $0 > "ofile.1"; next }
{ split(a[$1], old);
for (i = 2; i <= NF; i++)
{
if ($i != old[i])
{
format = "%-8s %4d %d %s\n"
printf format, "File1", $1, i, $i > "ofile.2";
printf format, "File2", $1, i, old[i] > "ofile.2";
}
}
}'
这在给定的假设下产生合理的输出(标题行不存在)。如果实际上标题行存在,那么你必须捕获它们并使用它们(以及文件名):
awk 'FNR == 1 { file[++num] = FILENAME; for (i = 1; i <= NF; i++) head[i] = $i; next }
NR == FNR { a[$1] = $0; next }
!($1 in a) { print $0 > "ofile.1"; next }
{ split(a[$1], old);
for (i = 2; i <= NF; i++)
{
if ($i != old[i])
{
format = "%-8s %4d %-4s %s\n"
printf format, file[1], $1, head[i], $i > "ofile.2";
printf format, file[2], $1, head[i], old[i] > "ofile.2";
}
}
}'
要在第二个输出文件上获得正确的标题,您需要进行一些小的调整:
awk 'NR == 1 { printf "%-8s %4s %-7s %s\n", "Filename", "Row", "Colname", "Colvalue" > "ofile.2" }
FNR == 1 { file[++num] = FILENAME; for (i = 1; i <= NF; i++) head[i] = $i; next }
NR == FNR { a[$1] = $0; next }
!($1 in a) { print $0 > "ofile.1"; next }
{ split(a[$1], old);
for (i = 2; i <= NF; i++)
{
if ($i != old[i])
{
format = "%-8s %4d %-7s %s\n"
printf format, file[1], $1, head[i], $i > "ofile.2";
printf format, file[2], $1, head[i], old[i] > "ofile.2";
}
}
}' File1 File2
此示例输出为:
ofile.1
3 M N O P
ofile.2
Filename Row Colname Colvalue
File1 1 Col2 Z
File2 1 Col2 B
File1 2 Col3 Y
File2 2 Col3 G
如果你想在每条记录后留空行,这是一个微不足道的修改 - OP的练习。