根据第一列中的唯一标题连接文件

时间:2014-05-05 06:00:32

标签: awk sed

我有很多两种列格式的文件,第一列中有标签,第二列中有数字。数字是正数(从不为零):

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文件的情况下执行此操作。谢谢......

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
  • 您将file1读入第1列索引的数组,并将整行指定为其值
  • 对于file2,检查数组中是否存在第1列。如果它打印file1中的值以及file2中的值。如果不存在则打印0作为file1的值。
  • 删除数组元素,只获取file1中唯一的元素。
  • END块中打印file1中唯一的内容,并为file2打印0。
  • 将输出管道传输到column -t以获得漂亮的格式。

答案 1 :(得分:0)

假设您的数据位于名为file1file2的文件中:

$ 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至少有一个占位符值为零。完成第二个文件后,将打印数据。

使用GNU Awk

的两个以上文件

我创建了一个文件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

此代码可以创建文件计数器。我们知道,每当FNR1并且计数器n递增时,我们就会处于新文件中。对于我们遇到的每一行,我们将数据放在二维数组中。 a的第一个维度是标签,第二个维度是我们遇到的文件的编号。最后,我们只循环遍历所有标签和所有文件,从1到{{1}并打印数据。

超过2个文件没有 GNU Awk

不需要GNU的awk,我们可以使用模拟的二维数组解决问题:

n