awk之NR==FNR,如何理解整理

编程

转载:https://www.cnblogs.com/irockcode/p/7044722.html

 

NR,表示awk开始执行程序后所读取的数据行数.

FNR,与NR功用类似,不同的是awk每打开一个新文件,FNR便从0重新累计.

下面看两个例子:

1,对于单个文件NR 和FNR 的 输出结果一样的 :

1

2

3

4

5

6

7

8

9

# awk "{print NR,$0}" file1

1 a b c d

2 a b d c

3 a c b d

 

#awk "{print FNR,$0}" file1

1 a b c d

2 a b d c

3 a c b d

  

2,但是对于多个文件 :

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

# awk "{print NR,$0}" file1 file2

1 a b c d

2 a b d c

3 a c b d

4 aa bb cc dd

5 aa bb dd cc

6 aa cc bb dd

 

# awk "{print FNR,$0}" file1 file2

1 a b c d

2 a b d c

3 a c b d

1 aa bb cc dd

2 aa bb dd cc

3 aa cc bb dd

  

在看一个例子关于NR和FNR的典型应用:

现在有两个文件格式如下:

1

2

3

4

5

6

7

8

#cat a

张三|000001

李四|000002

#cat b

000001|10

000001|20

000002|30

000002|15

  

想要得到的结果是将用户名,帐号和金额在同一行打印出来,如下:

张三|000001|10
张三|000001|20
李四|000002|30
李四|000002|15

执行如下代码

1

#awk -F | "NR==FNR{a[$2]=$0;next}{print a[$1]"|"$2}" a b

  

注释:

由NR=FNR为真时,判断当前读入的是第一个文件a,然后使用{a[$2]=$0;next}
循环将a文件的每行记录都存入数组a,并使用$2第2个字段作为下标引用.

由NR=FNR为假时,判断当前读入了第二个文件b,然后跳过{a[$2]=$0;next},
对第二个文件cdr的每一行都无条件执行{print a[$1]"|"$2},
此时变量$1为第二个文件的第一个字段,与读入第一个文件时,采用第一个文件第二个字段$2为数组下标相同.
因此可以在此使用a[$1]引用数组。

=========================================================================

下面是CU大神jason680的详细过程分析

awk -F"|" "NR==FNR{a[$2]=$0;next}{print a[$1] FS $2}" a b

There is no BEGIN block, and FS="|" by -F"|" argument
没有开始模块,直接识别-F选项,加参数

start to first file "a" 
从a文件的第一行开始
1. read file a line 1 and get data 张三|000001
读取文件a的第一行,得到数据
A: $0=张三|000001
B: $1=张三
C: $2=000001

NR and FNR are the same equal to 1, and run NR=FNR block
此时,NR与FNR的值相等都为1,执行NR=FNR模块
NR==FNR{a[$2]=$0;next}
A: a[$2]=$0
a[000001]=张三|000001
B: next
next cycle and get next line data 

2. read file a line 2 and get data 李四|000002
读取文件a的第二行,得到数据

A: $0=李四|000002
B: $1=李四
C: $2=000002

NR and FNR are the same equal to 2, and run NR=FNR block
此时,NR与FNR的值相等都为2,执行NR=FNR模块
NR==FNR{a[$2]=$0;next}
A: a[$2]=$0
a[000002]=李四|000002
B: next
next cycle and get next line data

end of the file a, and get next file b data
读完文件a,然后读取下一个文件b的数据

3. read file b line 1, and get data 000001|10
读取文件b的第一行,然后得到数据
A: $0=000001|10
B: $1=000001
C: $2=10

now, NR is 3 and FNR is 1, they are not eqaul
此时,NR与FNR的值不同,不执行NF=FNR模块,执行下一个模块{print a[$1] FS $2}
and didn"t run NR=FNR block, 
and run next block {print a[$1] FS $2} 
a[$1] => a[000001] => 张三|000001
FS => |
$2 => 10
you will see the output
张三|000001|10

4. read file b line 2, and get data 000001|20
A: $0=000001|20
B: $1=000001
C: $2=20

NR is 4 and FNR is 2, they are not eqaul
and didn"t run NR=FNR block, 
and run next block {print a[$1] FS $2} 
a[$1] => a[000001] => 张三|000001
FS => |
$2 => 20
you will see the output
张三|000001|20

cycle to read the file b 
5. read file b line 3, and get data 000002|30
...
output==> 李四|000002|30

6. read file b line 4, and get data 000002|15
...
output==> 李四|000002|15

 

 

补充:


找出两个文件之间的不同部分

awk "NR==FNR{a[$0]++} NR>FNR&&!a[$0]" 1.txt 2.txt

awk "NR==FNR{a[$0]}NR>FNR{ if(!($1 in a)) print $0}" 1.txt 2.txt

 

找出两个文件之间的相同部分

awk "NR==FNR{a[$0]++} NR>FNR&&a[$0]" 1.txt 2.txt

awk "NR==FNR{a[$0]}NR>FNR{ if($1 in a) print $0}" 1.txt 2.txt

 

以上是 awk之NR==FNR,如何理解整理 的全部内容, 来源链接: utcz.com/z/515290.html

回到顶部