我有这样的需求,需要把两个文件中,第一列相同的行合并到同一行中。举个例子,有两个文件,内容如下
cat 1.txt
1 aa2 bb
3 ee
4 ss
cat 2.txt
1 ab2 cd
3 ad
4 bd
5 de
合并后的结果为:
1 ab aa2 cd bb
3 ad ee
4 bd ss
5 de
实现的命令为:
awk 'NR==FNR{a[$1]=$2}NR>FNR{print $0,a[$1]}' 1.txt 2.txt
解释:NR表示读取的行数, FNR表示读取的当前行数,大家可以运行这个命令 awk '{print NR,FNR}' 1.txt 2.txt,比较NR和FNR
所以其实NR==FNR 就表示读取1.txt的时候。 同理NR>FNR表示读取2.txt的时候
数组a其实就相当于一个map
NR==FNR 是表示读取的第一个文件?
NR==FNR:用于在读取两个或两个以上的文件时,判断是不是在读取第一个文件[root@zhan sbin]# awk '{print NR,$0}' a.txt b.txt
1 1 aa
2 2 bb
3 3 ee
4 4 ss
5 1 ab
6 2 cd
7 3 ad
8 4 bd
9 5 de
[root@zhan sbin]# awk '{print FNR,$0}' a.txt b.txt
1 1 aa
2 2 bb
3 3 ee
4 4 ss
1 1 ab
2 2 cd
3 3 ad
4 4 bd
5 5 de
[root@zhan sbin]#
增加打印运行如下:
[root@bogon zhangsan]# cat 1.txt 2.txt
1 aa
2 bb
3 cc
1 ww
2 xx
3 yy
4 zz
[root@bogon zhangsan]# awk 'NR==FNR{a[$1]=$2;print a[$1],FNR,NR}NR>FNR{print $0,a[$1],FNR,NR}' 1.txt 2.txt
aa 1 1
bb 2 2
cc 3 3
1 ww aa 1 4
2 xx bb 2 5
3 yy cc 3 6
4 zz 4 7
無名世界 发表于 2014-8-8 09:51
反过来才是对的。NR=FNR时读取的是1.txt NR>FNR时读取的是2.txt
是的。 当空格数(NR)等于FNR是表示读取1.txt文件完毕,
当NR大于FNR是表示开在在读取2.txt
11 aa
22 bb
33 cc
44 dd
55 ee
[root@Master ~]# awk 'NR==FNR{a[$1]=$2}NR>FNR{print $0,a[$1]}' 1.txt 3.txt
aa
bb
cc
dd
ee
这个有点问题喃。。。并没有合并文件。。。
NR是所有的行数,FNR是正在读取的行数,先读1.txt再读2.txt
当读取1.txt时
第一行时:NR=0,FNR=0,
第二行时:NR=1,FNR=1,
……
最后一行时,NR=3,FNR=3,
然后开始读2.txt
读2.txt第一行时,NR=4,FNR=0,此时NR>FNR,所以开始打印第一行1 ab aa
第二行时,NR=5,FNR=2,同样满足NR>FNR,所以开始打印第二行2 cd bb
……
2.txt最后一行时,NR=7,FNR=4,打印最后一行5 de
从上面我们发现几个特点:
1、第二个文件有几行,就打印几行,因为只有读到第二个文件时,才满足NR>FNR,才能打印
2、NR、FNR都是从零开始计数,NR不清零,FNR读完一个文件后清零
3、行号后面列的顺序是在print中定义的,也可以定义先打1.txt的$2列,后打2.txt的$2列,改为{print a[$1],$0}即可。
附带说明(可以不看):
NR是number of records的缩写,记录的数量,在awk中行称为记录
FNR是file‘s number records的缩写,是当前文件的记录数,就是当前文件的行号
黄圣倨 - 与大家共勉,一起进步。
感觉awk蛮难的,不过可以使用paste命令实现这个需求
[root@hsj-01 ~]# cat a.txt
11111
22222
33333
[root@hsj-01 ~]# cat b.txt
aaaaa
bbbbb
[root@hsj-01 ~]# paste a.txt b.txt >c.txt
[root@hsj-01 ~]# cat c.txt
11111 aaaaa
22222 bbbbb
33333
编辑回复