如何用awk合并两个文件?

时间:2012-03-09 14:31:04

标签: awk

我有两个文件顺序相同,行数相同:

file1(只有2列):

562_201 RIR1
562_202 RIR1
562_203 RIR1
562_204 RIR1
562_205 RIR1
562_206 RIR1
562_207 RIR1
562_208 RIR1
562_209 RIR1
562_210 WR1 
562_211 WR1 
562_212 WR1 

file2(我应该说file2有超过百万行!):

562_201 0101
562_202 0101
562_203 0101
562_204 0101
562_205 0101
562_206 0101
562_207 0101
562_208 0101
562_209 0101
562_210 0101
562_211 0101
562_212 0101

我希望将它们合并到:

562_201 RIR1 0101
562_202 RIR1 0101
562_203 RIR1 0101
562_204 RIR1 0101
562_205 RIR1 0101
562_206 RIR1 0101
562_207 RIR1 0101
562_208 RIR1 0101
562_209 RIR1 0101
562_210 WR1  0101
562_211 WR1  0101
562_212 WR1  0101

谢谢!

4 个答案:

答案 0 :(得分:10)

您可以使用join命令:

$ join file1.txt file2.txt

答案 1 :(得分:6)

我不确定,但join命令可能会将这两个文件加载到内存中。如果一个或两个文件都很庞大,那可能会有问题。

这应该通过仅将较小的文件加载到内存中的数组中,然后通过管道连接数据来避免此问题。

#!/usr/bin/awk -f

# Load file1 into an array...
BEGIN {
  while (getline < "file1") {
    file1[$1]=$0;
  }
}

{
  key=$1;    # Store the key
  $1="";     # Blank the key (now $0 starts with the field separator)
  print file1[key] $0;
}

用法:

[ghoti@pc ~/tmp]$ ./join.awk file2
562_201 RIR1 0101
562_202 RIR1 0101
562_203 RIR1 0101
562_204 RIR1 0101
562_205 RIR1 0101
562_206 RIR1 0101
562_207 RIR1 0101
562_208 RIR1 0101
562_209 RIR1 0101
562_210 WR1 0101
562_211 WR1 0101
562_212 WR1 0101

正如格伦建议的那样,符号:

awk 'NR==FNR {file1[$1]=$0; next} {$1=file1[$1]; print}' file1 file2
对于将第一个文件加载到数组中的相同想法,

是一种更经典的方法。

如果这些包含数百万行的文件太大而无法存储在内存中,您还可以在自己的管道中逐步浏览每个文件,一次只能从每个文件加载一行到内存中:

$ awk '{getline line < "file1"; print line,$2}' file2

这将读取file2中的行,并且每行还会从file1读取一行到变量中,然后从file2打印变量和额外字段。一次只有一行存储在内存中。

按原样,它假定第一个字段在每个文件中始终匹配 - 也就是说,没有错误检查。如果你想要一些,很容易实现:

$ awk '{getline line < "file1"; split(line,a); if(a[1]!=$1) {exit(1)} print line,$2}' file2

如果$1不匹配,退出状态将退出。

答案 2 :(得分:5)

AWK

awk 'NR==FNR{a[$1]=$2;next;}gsub($1,$1" "a[$1])' file1 file2

答案 3 :(得分:2)

paste file1 file2 | awk '{$3=""; print}'

说明:

  1. paste f1 f2:逐行合并
  2. $3=""; print:删除重复的列