0、说明

刚好用到awk的NR和FNR这两个内建变量。经过一些测试大概熟悉其用法,这里记录下(本文只是用NR和FNR变量来判断当前读入的是第一个还是第二个文件,好对每个文件分别运行指定的脚本。需要注意的是只有读入的文件数小于或等于2个的时候才能使用NR和FNR来判断当前读入的是第几个文件,超过2个文件将无法判断)

1、NR和FNR的作用演示

NR和FNR都可以为awk读入的文件每行数据增加显示行号。不同之处在于当AWK读入多个文件的时候:NR的行号会一直增加下去,而FNR会在每读入一个新文件时将行号重新由1开始计算

1.1、首先创建两个示例文件

[root@imzcy ~]# cat user.txt #逗号分隔的三列分别表示:工号、姓名、部门编号

A0024,张三,10

A0019,李四,30

A0015,王五,40

A0021,孙六,80

[root@imzcy ~]#

[root@imzcy ~]# cat group.txt #逗号分隔的三列分别表示:部门编号、部门名称、部门位置

10,IT部,六层B区

20,财务部,七层C区

30,设计部,七层B区

40,人事部,六层C区

50,采购部,七层A区

60,招聘部,六层A区

70,法务部,七层D区

80,发展部,六层D区

90,总经办,六层E区

[root@imzcy ~]#

1.2、在AWK中调用NR变量,查看其作用

1.2.1、可以看到NR可以为读入的文件添加行号(行号从1开始,NR显示行号、$0显示行所有内容)

[root@imzcy ~]# awk '{print NR,$0}' user.txt

1 A0024,张三,10

2 A0019,李四,30

3 A0015,王五,50

4 A0021,孙六,80

[root@imzcy ~]#

1.2.2、根据下面输出可以看到,当NR读入多个文件的时候,行号会从上一个文件结束值增加的

[root@imzcy ~]# awk '{print NR,$0}' user.txt group.txt

1 A0024,张三,10

2 A0019,李四,30

3 A0015,王五,50

4 A0021,孙六,80

5 10,IT部,六层B区

6 20,财务部,七层C区

7 30,设计部,七层B区

8 40,人事部,六层C区

9 50,采购部,七层A区

10 60,招聘部,六层A区

11 70,法务部,七层D区

12 80,发展部,六层D区

13 90,总经办,六层E区

[root@imzcy ~]#

#1.3、在AWK中调用FNR变量,查看其作用

1.3.1、可以看到FNR同样也可以为读入的文件添加行号(行号从1开始,NR显示行号、$0显示行所有内容)

[root@imzcy ~]# awk '{print FNR,$0}' user.txt

1 A0024,张三,10

2 A0019,李四,30

3 A0015,王五,50

4 A0021,孙六,80

[root@imzcy ~]#

1.3.2、根据下面输出可以看到,当NR读入多个文件的时候,行号会从下一个文件开始时从新计算值增加的

[root@imzcy ~]# awk '{print FNR,$0}' user.txt group.txt

1 A0024,张三,10

2 A0019,李四,30

3 A0015,王五,50

4 A0021,孙六,80

1 10,IT部,六层B区

2 20,财务部,七层C区

3 30,设计部,七层B区

4 40,人事部,六层C区

5 50,采购部,七层A区

6 60,招聘部,六层A区

7 70,法务部,七层D区

8 80,发展部,六层D区

9 90,总经办,六层E区

[root@imzcy ~]#

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

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

1.1、首先创建两个示例文件

[root@imzcy~]# cat user.txt     #逗号分隔的三列分别表示:工号、姓名、部门编号

A0024,张三,10

A0019,李四,30

A0015,王五,40

A0021,孙六,80

[root@imzcy~]#

[root@imzcy~]# cat group.txt    #逗号分隔的三列分别表示:部门编号、部门名称、部门位置

10,IT部,六层B区

20,财务部,七层C区

30,设计部,七层B区

40,人事部,六层C区

50,采购部,七层A区

60,招聘部,六层A区

70,法务部,七层D区

80,发展部,六层D区

90,总经办,六层E区

[root@imzcy~]#

1.2、在AWK中调用NR变量,查看其作用

1.2.1、可以看到NR可以为读入的文件添加行号(行号从1开始,NR显示行号、$0显示行所有内容)

[root@imzcy~]# awk '{print NR,$0}' user.txt

1A0024,张三,10

2A0019,李四,30

3A0015,王五,50

4A0021,孙六,80

[root@imzcy~]#

1.2.2、根据下面输出可以看到,当NR读入多个文件的时候,行号会从上一个文件结束值增加的

[root@imzcy~]# awk '{print NR,$0}' user.txt group.txt

1A0024,张三,10

2A0019,李四,30

3A0015,王五,50

4A0021,孙六,80

510,IT部,六层B区

620,财务部,七层C区

730,设计部,七层B区

840,人事部,六层C区

950,采购部,七层A区

1060,招聘部,六层A区

1170,法务部,七层D区

1280,发展部,六层D区

1390,总经办,六层E区

[root@imzcy~]#

#1.3、在AWK中调用FNR变量,查看其作用

1.3.1、可以看到FNR同样也可以为读入的文件添加行号(行号从1开始,NR显示行号、$0显示行所有内容)

[root@imzcy~]# awk '{print FNR,$0}' user.txt

1A0024,张三,10

2A0019,李四,30

3A0015,王五,50

4A0021,孙六,80

[root@imzcy~]#

1.3.2、根据下面输出可以看到,当NR读入多个文件的时候,行号会从下一个文件开始时从新计算值增加的

[root@imzcy~]# awk '{print FNR,$0}' user.txt group.txt

1A0024,张三,10

2A0019,李四,30

3A0015,王五,50

4A0021,孙六,80

110,IT部,六层B区

220,财务部,七层C区

330,设计部,七层B区

440,人事部,六层C区

550,采购部,七层A区

660,招聘部,六层A区

770,法务部,七层D区

880,发展部,六层D区

990,总经办,六层E区

[root@imzcy~]#

2、接下来拿一个工作中用到的一段命令做示例讲解下(做了修改)

比如根据上面user.txt和group.txt两个文件,我现在要直接显示出来user.txt文件里那几个员工的:姓名、员工编号、部门名称。则可以用下面命令

2.1、根据user.txt和group.txt文件信息,直接输出:员工姓名,员工编号,部门名称

[root@imzcy ~]# awk -F , 'NR==FNR{Z[$3]=$2","$1}NR>FNR{print Z[$1]","$2}' user.txt group.txt

张三,A0024,IT部

,财务部

李四,A0019,设计部

,人事部

王五,A0015,采购部

,招聘部

,法务部

孙六,A0021,发展部

,总经办

[root@imzcy ~]#

因为group.txt里面有的部门在user.txt那个文件中没有,并且我直接打印了$2,所以也都会显示出来

2.2、加if语句做判断,只有当数组Z[$1]对应的值不为空的时候,才会打印出$2的值。

[root@imzcy ~]# awk -F , 'NR==FNR{Z[$3]=$2","$1}NR>FNR{if(Z[$1]!=""){print Z[$1]","$2}}' user.txt group.txt

张三,A0024,IT部

李四,A0019,设计部

王五,A0015,采购部

孙六,A0021,发展部

[root@imzcy ~]#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

2.1、根据user.txt和group.txt文件信息,直接输出:员工姓名,员工编号,部门名称

[root@imzcy~]# awk -F , 'NR==FNR{Z[$3]=$2","$1}NR>FNR{print Z[$1]","$2}' user.txt group.txt

张三,A0024,IT部

,财务部

李四,A0019,设计部

,人事部

王五,A0015,采购部

,招聘部

,法务部

孙六,A0021,发展部

,总经办

[root@imzcy~]#

因为group.txt里面有的部门在user.txt那个文件中没有,并且我直接打印了$2,所以也都会显示出来

2.2、加if语句做判断,只有当数组Z[$1]对应的值不为空的时候,才会打印出$2的值。

[root@imzcy~]# awk -F , 'NR==FNR{Z[$3]=$2","$1}NR>FNR{if(Z[$1]!=""){print Z[$1]","$2}}' user.txt group.txt

张三,A0024,IT部

李四,A0019,设计部

王五,A0015,采购部

孙六,A0021,发展部

[root@imzcy~]#

3、语句运行过程详细说明

就拿下面这个awk脚本做说明

[root@imzcy ~]# awk -F , 'NR==FNR{Z[$3]=$2","$1}NR>FNR{print Z[$1]","$2}' user.txt group.txt

1

[root@imzcy~]# awk -F , 'NR==FNR{Z[$3]=$2","$1}NR>FNR{print Z[$1]","$2}' user.txt group.txt

3.1、总体运行过程如下:

1、首先根据你给定顺序读入第一个文件user.txt,然后将使用'NR==FNR{Z[$3]=$2","$1}NR>FNR{print Z[$1]","$2}' 对user.txt及后面其他文件每行内容做处理。

2、例如当读入第一行数据A0024,张三,10后,首先判断NR==FNR是否为真(因为现在读入的是第一个文件,此时NR和FNR的行号是相等的,所以为真),为真则运行其后面的那段脚本{Z[$3]=$2","$1} ;上面那段脚本运行完后,因为后面还有脚本所以会继续向后运行,此时判断NR>FNR是否为真(因为现在读入的是第一个文件,此时NR和FNR的行号是相等的,所以并不会大于,此处为假),为假时跳过执行其后面的脚本{print Z[$1]","$2}开始处理下一行数据。

3、当第一个文件的所有条目都处理完毕之后,开始读入第二个文件数据。

4、例如当前读入第一行数据10,IT部,六层B区 ,首先判断NR==FNR是否为真(因为现在读入的是第二个文件了,此时NR值增加,FNR则从1开始,所以并不相等,此时为假),为假时跳过执行其后面脚本{Z[$3]=$2","$1} ; 继续向下运行,开始判断NR>FNR是否为真(因为读入的第二个文件,NR值增加,FNR值从1开始重新计算,所以NR大于FNR,此时为真),为真则执行后面脚本{print Z[$1]","$2} 然后开始处理下一行数据

5、当每个文件都处理完则结束。

3.2、user.txt文件每行数据执行{Z[$3]=$2","$1} 脚本时过程:

1、执行脚本为Z[$3]=$2","$1 就是定义了一个数组Z,其下标名为$3的值为$2(做变量替换)。

2、例如此时读入第一行数据:A0024,张三,10 相当于定义了数组Z[10]=张三,A0024 (定义数组Z下标为10的值等于字符串张三,A0024)

3、读入user.txt第二行数据A0019,李四,30 相当于定义Z[30]=李四,A0019 (数组Z下标为30的值等于字符串李四,A0019)

4、后面都一样。

3.3、group.txt文件每行数据执行{print Z[$1]","$2}' 脚本时过程:

1、执行脚本print Z[$1]","$2 就是直接输出数组指定下标及变量对应的值。

2、例如此时读入第一行数据:10,IT部,六层B区 ,相当于print打印 Z[10]","IT部 ,也就是张三,A0024,IT部 (因为前面处理第一个文件数据时已经定好了数组Z,下标为10的值是张三,A0024,然后此处读入的group.txt文件的第一行数据$1的值是10,直接替换引用了),然后继续向下处理下一行数据。

3、读入group.txt第二行数据20,财务部,七层C区 ,相当于打印Z[20]","财务部 ,但是因为前面处理第一个文件user.txt时,其中并没有属于财务部的员工,所以部门编号为20的对应数组下标并没有被定义值,所以这里Z[20]的值就为空,所以最终会打印机出来,财务部

4、后面就都一样了

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐