关于awk:在gawk中加入多个文件

Join multiple files in gawk

我有很多文件(大约500个)。每个文件包含两列。第一列对于每个文件都是相同的。我想使用gawk将所有文件连接到一个文件中。例如,

1
2
3
4
File 1  
a 123  
b 221  
c 904

1
2
3
4
File 2
a 298  
b 230  
c 102

等等。我想要一个像下面这样的最终文件:

1
2
3
4
Final file
a 123 298  
b 221 230  
c 904 102

我找到了可以连接两个文件的脚本,但我需要连接多个文件。


对于给定的示例文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ head f*
==> f1 <==
a 123
b 221
c 904

==> f2 <==
a 298
b 230
c 102

==> f3 <==
a 500
b 600
c 700

号方法1:

1
2
3
4
$ awk '{a[FNR]=((a[FNR])?a[FNR]FS$2:$0)}END{for(i=1;i<=FNR;i++) print a[i]}' f*
a 123 298 500
b 221 230 600
c 904 102 700

方法2:(可能会更快,因为您没有在内存中加载500个文件)

同时使用pasteawk。(假设第一列相同,并且存在于所有文件中)。执行EDOCX1[2]将得到以下结果:

1
2
3
4
$ paste f*
a 123   a 298   a 500
b 221   b 230   b 600
c 904   c 102   c 700

通过管道将其输送至awk,以移除额外的柱子。

1
2
3
4
$ paste f* | awk '{printf"%s",$1;for(i=2;i<=NF;i+=2) printf"%s%s",$i,(i==NF?RS:FS)}'
a 123 298 500
b 221 230 600
c 904 102 700

您可以将输出重新定向到另一个文件。


我经常遇到这个问题。

我强烈建议您检查gawk中的getline功能。

1
getline var < filename

是命令语法,可以用来解决问题。

我建议使用另一种更容易解决这个问题的语言。通常我会投资5行代码来解决这个标准问题。

1
2
3
4
5
6
j=1;
j=getline x <"filename";
if(j==0) {
      break;
}
... (Commands involving x such as split and print).


1
awk 'FNR==NR{arr[$1]=$2; next;}{printf"%s%s%s%s%s",$1,OFS,arr[$1],OFS,$2; print"";}' file1 file2

基于此


您可以尝试如下操作:

1
2
3
4
5
6
$ ls
f1.txt  f2.txt  f3.txt
$ awk '($0 !~ /#/){a[$1]=a[$1]""$2} END {for(i in a){print i""a[i]}}' *.txt
a 123 298 299
b 221 230 231
c 904 102 103