0、说明
刚好用到awk的NR和FNR这两个内建变量。经过一些测试大概熟悉其用法,这里记录下(本文只是用NR和FNR变量来判断当前读入的是第一个还是第二个文件,好对每个文件分别运行指定的脚本。需要注意的是只有读入的文件数小于或等于2个的时候才能使用NR和FNR来判断当前读入的是第几个文件,超过2个文件将无法判断)
1、NR和FNR的作用演示
NR和FNR都可以为awk读入的文件每行数据增加显示行号。不同之处在于当AWK读入多个文件的时候:NR的行号会一直增加下去,而FNR会在每读入一个新文件时将行号重新由1开始计算
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 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 ~]# |
2、接下来拿一个工作中用到的一段命令做示例讲解下(做了修改)
比如根据上面user.txt和group.txt两个文件,我现在要直接显示出来user.txt文件里那几个员工的:姓名、员工编号、部门名称。则可以用下面命令
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脚本做说明
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、后面就都一样了