我有两个具有相同标题和结构的文件,第一列是键。
文件一:
key val1 val2 val3 val4 val5
Item1 10 12 44 88 22
Item2 33 33 43 77 22
Item3 28 44 55 22 11
Item4 12 55 55 14 44
文件2:
key val1 val2 val3 val4 val5
Item1 10 11 44 99 22
Item2 33 33 43 77 22
Item3 28 44 55 22 11
Item4 12 55 55 14 00
正如您在上面的文件中注意到的,这两个文件有两个不同之处:
- item1 的 val2 和 val4 不同
- 第 4 项的 val5 不同
所以我想生成一个比较输出,它应该告诉我哪个项目的哪些字段不同。输出应该类似于:
Item1: val2,val4
Item4: val5
答案1
awk -v ref=file1 '
{
getline refline <ref
if (NR == 1) split(refline, head)
nf = split(refline, a)
for (i = 1; i <= nf; ++i)
if ($i != a[i])
diffcol[++n] = i
if (n > 0) {
$0 = a[1]
for (i = 1; i <= n; ++i)
$(i+1) = head[diffcol[i]]
print
n = 0
}
}' file2
这会将您的文件file2
与“参考文件”进行比较file1
。 from 的行file2
通常由 读取awk
,而 from 的行则通过在代码中调用并用 分割来file1
显式读取。getline
awk
split
该split(refline, head)
块将数组设置head
为标头,从 读取file1
。这仅对来自 的第一行输入执行file2
。
第一个循环比较两个文件之间的字段以及任何不同且附加到diffcol
数组的字段的列号。
如果发现一个或多个差异,则将输出 的第一个字段,后跟不同file1
字段(来自 )的标题。file1
我编写代码的方式,标题行和第一个字段也受到比较,因此如果在第一个字段中发现差异,您也会得到一行输出,可能在key
开始时该行的(因为这是 中第一个字段的值file1
)。
该代码不假设两个文件中的列数相同。
鉴于您问题中的数据,您将从该代码中获得以下输出:
Item1 val2 val4
Item4 val5
答案2
paste
使用 和的组合awk
,假设所有记录具有相同数量的字段:
paste file1 file2 |
awk -F'\t' '
NR == 1 {cols = split($0, hdr) / 2; next}
{
diff = sep = ""
for (i = 2; i <= cols; i++)
if ($i "" != $(i+cols) "") {
diff = diff sep hdr[i]
sep = ","
}
if (sep) print $1": "diff
}'
我们附加""
到比较的每一侧,!=
以便比较始终是词汇的(0
不同于00
or -0
、inf
from infinity
、 1e500 等)。当字段看起来像数字时,删除这些字段以便比较为数字。