awk 中的NR==FNR

Linux awk NR==FNR

在使用awk的时, 如果能会利用NR==FNR这种方式, 那么可以处理许多情况。
计算两个文件的交集, 在一个文件中有,在另一个文件中没有等等。

NR

NR The total number of input records seen so far.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ cat file1
a
b
c

$ cat file2
d
e

$ awk '{print FILENAME, NR, $0}' file1
file1 1 a
file1 2 b
file1 3 c

$ awk '{print FILENAME, NR, $0}' file1 file2
file1 1 a
file1 2 b
file1 3 c
file2 4 d
file2 5 e

$ awk '{print FILENAME, NR, $0}' file2 file1
file2 1 d
file2 2 e
file1 3 a
file1 4 b
file1 5 c

FNR

FNR The input record number in the current input file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ awk '{print FILENAME, NR, FNR, $0}' file1 
file1 1 1 a
file1 2 2 b
file1 3 3 c

$ awk '{print FILENAME, NR, FNR, $0}' file1 file2
file1 1 1 a
file1 2 2 b
file1 3 3 c
file2 4 1 d
file2 5 2 e

$ awk '{print FILENAME, NR, FNR, $0}' file2 file1
file2 1 1 d
file2 2 2 e
file1 3 1 a
file1 4 2 b
file1 5 3 c

NR==FNR

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ awk 'NR==FNR{print FILENAME, NR, FNR, $0}' file1 file2 
file1 1 1 a
file1 2 2 b
file1 3 3 c
# 当条件NR==FNR时,file1文件符合,file2文件不符合,所以只输出了file1文件

$ awk 'NR==FNR{a[$0]; print FILENAME, $0}' file1 file2
file1 a
file1 b
file1 c
# 这里a[$0] a是一个数组 将file1中的每行内容,放在了a这个数组中

$ awk 'NR==FNR{a[$0];}{print FILENAME, $0}' file1 file2
file1 a
file1 b
file1 c
file2 d
file2 e
# 符合NR==FNR条件才会执行第一个{}中的内容, 第二个{}中内容都会执行

$ awk 'NR==FNR{a[$0]; next;}{print FILENAME, $0}' file1 file2
file2 d
file2 e

# 符合NR==FNR条件才会执行第一个{},next关键字类似于代码中continue。后面的语句没有执行,只有当NR!=FNR才会执行后面的语句

实践

1
2
3
4
5
6
7
8
9
10
11
$ cat a.txt 
a
b
c
d

$ cat b.txt
b
c
d
e

在a.txt和b.txt中都有

1
2
3
4
$ awk 'NR==FNR{a[$0]; next} $0 in a {print FILENAME, $0}' a.txt b.txt 
b.txt b
b.txt c
b.txt d

在b.txt中有, a.txt中没有

1
2
$ awk 'NR==FNR{a[$0]; next} {if (!($0 in a)) print FILENAME, $0}' a.txt b.txt 
b.txt e

a.txt中有的 b.txt中没有; b.txt中有的 a.txt中没有

1
2
3
$ cat a.txt b.txt  | sort -n | uniq -c | awk '{if ($1 == 1) print $2}'
a
e

xpisme wechat
微信号