我正在尝试合并两个制表符分隔的文件文件 - 这些文件的长度不等。 我需要根据列号1合并文件,并从每个文件的第3列获取值到新文件。如果任何文件缺少任何id(不常见的值),那么它应该在新文件中得到一个空白值 -
File1:
id1 2199 082
id2 0909 20909
id3 8002 8030
id4 28080 80828
File2:
id1 988 00808
id2 808 80808
id4 8080 2525
id6 838 3800
Merged file :
id1 082 00808
id2 20909 80808
id3 8030
id4 80828 2525
id6 3800
我经历了很多论坛和帖子,到目前为止,我有这个
awk -F\t 'NR==FNR{A[$1]=$1; B[$1]=$1; next} {$2=A[$1]; $3=B[$1]}1'
但它没有产生正确的结果,任何人都可以建议。非常感谢!
答案 0 :(得分:4)
$ awk -F'\t' 'NR==FNR{A[$1]=$3; next} {A[$1]; B[$1]=$3} END{for (id in A) print id,A[id],B[id]}' OFS='\t' File1 File2 | sort
id1 082 00808
id2 20909 80808
id3 8030
id4 80828 2525
id6 3800
此脚本使用两个变量。对于File1中的每一行,关联数组A
都有一个对应于id和第三个字段值的键。对于File2中的每个id,A
也有一个键(但不一定是值)。对于File2,数组B
具有每个id的键,其中包含来自第三列的相应值。
-F'\t'
这会将输入中的字段分隔符设置为选项卡。请注意,必须引用\t
以保护它免受外壳攻击。
NR==FNR{A[$1]=$3; next}
这为第一个文件设置关联数组A
。
A[$1]; B[$1]=$3
这为第二个文件设置关联数组。它还确保数组A
具有file2中每个id的键。
END{for (id in A) print id,A[id],B[id]}
打印出结果。
OFS='\t'
这会将输出字段分隔符设置为选项卡。
sort
不保证awk构造for key in array
以任何特定顺序返回密钥。我们使用sort
在id中按升序对输出进行排序。
答案 1 :(得分:4)
假设没有重复的ID,您可以尝试(在-F$'\t'
使用Bash):
awk -F$'\t' 'BEGIN { OFS=FS } NR==FNR { A[$1] = $3; next }
{ if ($1 in A) print $1, A[$1], $3
else print $1, " ", $3
delete A[$1]
}
END { for (i in A) print i, A[i], " " }
' File1 File2
设置输出字段分隔符。对于第一个文件中的行,捕获由列1索引的数组A
中第一个文件的字段3.对于第二个(或后续)文件中的行,如果在A
中找到ID列,打印三列;否则,在A
中打印空格代替缺失的条目。使用完毕后删除A
中的条目。最后,剩下的所有行都会打印出第二个文件中缺少的条目的空白。
对于给定的数据,输出的示例是:
id1 082 00808
id2 20909 80808
id4 80828 2525
id6 3800
id3 8030
显然,如果您希望以特定方式对数据进行排序,则可以使用awk
命令对sort
命令进行后置过滤(意味着将awk
的输出传递给{ {1}})。
答案 2 :(得分:2)
另一个类似的awk
$ awk -v OFS='\t' 'NR==FNR{a[$1]=$3; next}
{$2=$3; $3=a[$1]; delete a[$1]} 1;
END{for(k in a) print k,"",a[k]} ' file2 file1
id1 082 00808
id2 20909 80808
id3 8030
id4 80828 2525
id6 3800
首先使用file2来匹配给定的输出但是不能保证订购,如果你的密钥有自然顺序,你可以按它们排序。
答案 3 :(得分:1)
使用sorted_in
的GNU awk:
$ cat tst.awk
BEGIN { FS=OFS="\t" }
{ a[$1] = (NR>FNR ? a[$1] OFS : "") $3 }
END {
PROCINFO["sorted_in"] = "@ind_str_asc"
for (k in a) {
print k, a[k]
}
}
$ awk -f tst.awk file1 file2
id1 082 00808
id2 20909 80808
id3 8030
id4 80828 2525
id6 3800
使用其他awk只需将输出传递给sort
。