awk 合并一个文件

回复 收藏
awk

我有这样的需求,需要把两个文件中,第一列相同的行合并到同一行中。举个例子,有两个文件,内容如下

cat 1.txt

1 aa
2 bb
3 ee
4 ss

cat 2.txt

1 ab
2 cd
3 ad
4 bd
5 de

合并后的结果为:

1 ab aa
2 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

2011-01-24 17:10 举报
已邀请:
0

古峰

赞同来自:

还是不,明白
0

無名世界

赞同来自:

反过来才是对的。NR=FNR时读取的是1.txt          NR>FNR时读取的是2.txt
0

赞同来自:

不明白
0

gjc159357

赞同来自:

好抽象
0

qqq998492

赞同来自:

本帖最后由 qqq998492 于 2015-9-15 11:36 编辑

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]#


0

cdhelloworld

赞同来自:

  1. awk 'NR==FNR{a[FNR]=$0}NR>FNR{print $0,a[FNR]}' a.txt b.txt
0

zhangsan

赞同来自:

NR和FNR相等时,即awk处理的当前行和文件的行数相同时,也即读取第一个文件时,将第二列的值赋给数组a(数组下标为第一列的值,这也就是为何题目要求不同文件第一列相同),NR>FNR,即处理第二个文件时,以下标为索引,将数组a中的值连同第二个文件所有值一起打印。
增加打印运行如下:
[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
0

ヾSun

赞同来自:

学习了
0

starry

赞同来自:

也许换个写法能容易看懂些
awk '{if (NR==FNR) a[$1]=$2};{if (NR>FNR) print $0,a[$1]}' 1.txt 2.txt
0

yonself

赞同来自:

無名世界 发表于 2014-8-8 09:51
反过来才是对的。NR=FNR时读取的是1.txt          NR>FNR时读取的是2.txt

是的。 当空格数(NR)等于FNR是表示读取1.txt文件完毕,
当NR大于FNR是表示开在在读取2.txt
0

gxp2008

赞同来自:

关健是行号
0

善思致用

赞同来自:


不错,更具有通用性
0

JohnJin

赞同来自:

無名世界 发表于 2014-8-8 09:51
反过来才是对的。NR=FNR时读取的是1.txt          NR>FNR时读取的是2.txt

+1
0

kevinjin

赞同来自:

不明白,为什么NR==FNR不能表示1.txt ?
0

hegeng

赞同来自:

学习了
0

Kry1702

赞同来自:

[root@Master ~]# paste 1.txt 3.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
这个有点问题喃。。。并没有合并文件。。。
0

Supernatural - 个人博客:http://www.cnblogs.com/yshan13/

赞同来自:

学习了。==时读取第一个文件
0

king锦韬

赞同来自:

铭哥,不是太懂,解释得清楚点嘛
0

多面体

赞同来自:

学习

0

喀洛池

赞同来自:

比较抽象,先记住吧

0

大苏湖

赞同来自:

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的缩写,是当前文件的记录数,就是当前文件的行号

0

派派菠菜

赞同来自:

NR表示打印出来的内容的第N行

FNR表示依次几个文件的第N行

应该是这样理解的吧?

0

黄圣倨 - 与大家共勉,一起进步。

赞同来自:

感觉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       

0

蓑笠翁

赞同来自:

为什么NR==FNR 就表示读取2.txt 而NR>FNR 就表示读取1.txt?如何理解

0

傲立

赞同来自:

这个已经默认了第一列要按照顺序来。你稍微改一下第一列的顺序,它问题很大。

[root@shuai-01 awk]# cat 1.txt

1 aa

2 bb

3 ee

4 ss

[root@shuai-01 awk]# cat 2.txt

1 ab

3 cd

4 ad

5 bd

6 de

[root@shuai-01 awk]# awk 'NR==FNR {a[$1]=$2} NR>FNR {print $0,a[$1]}' 1.txt 2.txt

1 ab aa

3 cd ee

4 ad ss

5 bd 

6 de 

第一列为2的不见了。

回复帖子,请先登录注册

退出全屏模式 全屏模式 回复
评分
可选评分理由: