我有很多两种列格式的文件,第一列中有标签,第二列中有数字。数字是正数(从不为零):
AGS 3
KET 45
WEGWET 12
FEW 56
在每个文件中,标签不会重复。
我想将这么多文件连接成一个包含多个+ 1列的文件,这样第一列包含所有文件中所有标签的唯一集合,最后五列包含每个文件的每个标签的编号。如果标签不存在于某个文件中(因此没有数字),我希望它默认为零。例如,如果第二个文件包含:
AGS 5
KET 14
KJV 2
FEW 3
然后最终输出如下:
AGS 3 5
KET 45 14
WEGWET 12 0
KJV 0 2
FEW 56 3
我是Linux的新手,并且一直在使用sed和awk,但是意识到这可能需要多个步骤......
*编辑注释:我必须将其从2个文件更改为多个文件。尽管我的示例仅显示了2个文件,但我想在> 2文件的情况下执行此操作。谢谢......
答案 0 :(得分:1)
以下是使用awk
的一种方式:
awk '
NR==FNR {a[$1]=$0;next}
{
print (($1 in a)?a[$1] FS $2: $1 FS "0" FS $2)
delete a[$1]
}
END{
for (x in a) print a[x],"0"
}' file1 file2 | column -t
AGS 3 5
KET 45 14
KJV 0 2
FEW 56 3
WEGWET 12 0
0
作为file1的值。 END
块中打印file1中唯一的内容,并为file2打印0。column -t
以获得漂亮的格式。 答案 1 :(得分:0)
假设您的数据位于名为file1
和file2
的文件中:
$ awk 'FNR==NR {a[$1]=$2; b[$1]=0; next} {a[$1]+=0; b[$1]=$2} END{for (x in b) {printf "%-15s%3s%3s\n",x,a[x],b[x]}}' file1 file2
KJV 0 2
WEGWET 12 0
KET 45 14
AGS 3 5
FEW 56 3
要理解上述内容,我们必须了解awk
技巧。
在awk
中,NR
是已处理的记录(行)数,FNR
是我们在当前文件中处理的记录数。因此,仅当我们在第一个文件中处理时,条件FNR==NR
才为真。在这种情况下,关联数组a
获取第一个文件中的所有值,关联数组b
获取占位符,即零值。当我们处理第二个文件时,它的值在数组b
中,我们确保数组a
至少有一个占位符值为零。完成第二个文件后,将打印数据。
我创建了一个文件3:
$ cat file3
AGS 3
KET 45
WEGWET 12
FEW 56
AGS 17
ABC 100
扩展为使用任意数量文件的awk程序是:
$ awk 'FNR==1 {n+=1} {a[$1][n]=$2} END{for (x in a) {printf "%-15s",x; for (i=1;i<=n;i++) {printf "%5s",a[x][i]};print ""}}' file1 file2 file3
KJV 2
ABC 100
WEGWET 12 12
KET 45 14 45
AGS 3 5 17
FEW 56 3 56
此代码可以创建文件计数器。我们知道,每当FNR
为1
并且计数器n
递增时,我们就会处于新文件中。对于我们遇到的每一行,我们将数据放在二维数组中。 a
的第一个维度是标签,第二个维度是我们遇到的文件的编号。最后,我们只循环遍历所有标签和所有文件,从1到{{1}并打印数据。
不需要GNU的awk,我们可以使用模拟的二维数组解决问题:
n