2013-03-12 124 views
1

我想将两个文件合并为一行一行,并使用前三列作为关键字。例如:如何使用awk合并基于前三列的两个文件

FILE1.TXT

a b c 1 4 7 
x y z 2 5 8 
p q r 3 6 9 

FILE2.TXT

p q r 11 
a b c 12 
x y z 13 

我期望用于上述两个文件输出是:

a b c 1 4 7 12 
x y z 2 5 8 13 
p q r 3 6 9 11 

列中的每个文件的数目不是固定的,它可以因行而异。而且,我在每个文件中获得了超过27K行。

他们没有订购。他们唯一的区别是前两个文件的前三个字段是相同的。

+0

我已经投票结束这个问题,因为它似乎是一个工具或解决方案的建议的请求,而不是请求帮助您自己的代码。这使您的问题脱离了StackOverflow。如果该评估不正确,并且确实需要编写自己的代码,请[将您的工作添加到您的问题中](https://stackoverflow.com/posts/15366829/edit),然后我将收回我的近距离投票。 – ghoti 2017-08-08 20:25:54

回答

0

试试这个:

awk 'NR==FNR{a[$1$2$3]=$4;next}$1$2$3 in a{print $0, a[$1$2$3]}' file2 file1 
+0

这假设完全是4列。它还假定连接前三列产生一个唯一键(对于示例输入为true,但对于真实文件可能不是这样)。 – OpenSauce 2013-03-12 16:40:50

+2

@OpenSauce OP知道真实文件的格式。如果OP有这样的要求,我可以改变代码 – Kent 2013-03-12 16:50:09

+0

,这部分很容易解决,但我想指出,如果OP不知道。但更大的问题是“每个文件中的列数不固定,可能因行而异”。你只需要在你的数组中保存'$ 4',但我认为你需要从'$ 4'循环到'NF'。 – OpenSauce 2013-03-12 16:59:32

0

如果列具有不同的长度,你可以使用SUBSEP尝试是这样的:

awk 'NR==FNR{A[$1,$2,$3]=$4; next}($1,$2,$3) in A{print $0, A[$1,$2,$3]}' file2 file1 

用于改变文件1列进行排序输出,尝试:

awk '{$1=$1; i=$1 FS $2 FS $3 FS; sub(i,x)} NR==FNR{A[i]=$0; next}i in A{print i $0, A[i]}' file2 file1 | sort 
+0

file2有7个固定列,但file1可以有3个或更多。如果它适用于带有3列的file1,也是可以的。我希望它们按照它们在file1中的方式进行排序。非常感谢。 – user2161903 2013-03-12 17:44:23

+0

添加了一个变体 – Scrutinizer 2013-03-14 10:04:01

1

您也可以使用join,它需要排序输入,并且前3个字段被合并。下面排序的每个文件的例子中,让sed合并和分隔字段:

join <(sort file1.txt | sed 's/ /-/; s/ /-/') \ 
    <(sort file2.txt | sed 's/ /-/; s/ /-/') | 
sed 's/-/ /; s/-/ /' 

输出:

a b c 1 4 7 12 
p q r 3 6 9 11 
x y z 2 5 8 13 
1

加入在第一三个字段,其中字段的数量是可变的(四个或更多个)

{ 
    # get the forth field until the last 
    for (i=4;i<=NF;i++) 
     f=f$i" " 

    # concat fields 
    arr[$1OFS$2OFS$3]=arr[$1OFS$2OFS$3]f; 
    # reset field string 
    f=""  
}  
END { 
    for (key in arr) 
     print key, arr[key]  
} 

运行,如:

$ awk -f script.awk file1 file2 
a b c 1 4 7 12 
p q r 3 6 9 11 
x y z 2 5 8 13