关于awk中NR、FNR、NF、$NF、FS、OFS的说明

一、NR和FNR
1.释义
NR: 表示当前读取的行数
FNR:当前修改了多少行


2.举例
比如现在AWK处理到第五行。第一行没有进行操作,2,3,4,5行进行了操作,那么NR=5,FNR=4
NR==FNR 表示从起始行到当前行,awk都进行了操作,比如修改,添加等等 ;

二、NF和$NF
1.释义
NF:浏览记录的域的个数
$NF: 最后一个列,输出最后一个列的内容

2.举例
[root@vshi-template shell]# pwd
/root/guanyy/scripts/shell
[root@vshi-template shell]# echo $PWD|awk -F/ '{print $NF}'
shell
[root@vshi-template shell]# echo $PWD|awk -F/ '{print NF}'
5

三、FS和OFS

1.释义
FS:指定列分隔符, 当FS为空的时候,awk会把一行中的每个字符,当成一列来处理。
OFS:列输出分隔符

2.举例
(1)FS指定列分隔符

  1. [zhangy@localhost test]$ echo "111|222|333"|awk '{print $1}'  
  2.  111|222|333  
  3. [zhangy@localhost test]$ echo "111|222|333"|awk 'BEGIN{FS="|"}{print $1}'  
  4.  111  
 

(2)FS也可以使用正则

  1. [zhangy@localhost test]$ echo "111||222|333"|awk 'BEGIN{FS="[|]+"}{print $1}'  
  2. 111  


(3)FS为空时

  1. [zhangy@localhost test]$ echo "111|222|333"|awk 'BEGIN{FS=""}{NF++;print $0}'  
  2. 1 1 1 | 2 2 2 | 3 3 3  

(4)RS被设定成非 时, 会成FS分割符中的一个

  1. [zhangy@localhost test]$ cat test1  
  2.  111 222  
  3.  333 444  
  4.  555 666  
  5. [zhangy@localhost test]$ awk 'BEGIN{RS="444";}{print $2,$3}' test1  
  6.  222 333  
  7.  666  

(5)OFS列输出分隔符

  1. [zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $1,$2}' test1  
  2.  111|222  
  3.  333|444  
  4.  555|666  
  5. [zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $1 OFS $2}' test1  
  6.  111|222  
  7.  333|444  
  8.  555|666  

test1只有二列,如果100列,都写出来太麻烦了吧。

  1. [zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $0}' test1  
  2.  111 222  
  3.  333 444  
  4.  555 666  
  5. [zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{NF=NF;print $0}' test1  
  6.  111|222  
  7.  333|444  
  8.  555|666  

为什么第二种方法中的OFS生效呢?个人觉得,awk觉查到列有所变化时,就会让OFS生效,没变化直接输出了。

NR表示从awk开始执行后,按照记录分隔符读取的数据次数,默认的记录分隔符为换行符,因此默认的就是读取的数据行数,NR可以理解为Number of Record的缩写。

  在awk处理多个输入文件的时候,在处理完第一个文件后,NR并不会从1开始,而是继续累加,因此就出现了FNR,每当处理一个新文件的时候,FNR就从1开始计数,FNR可以理解为File Number of Record。

  NF表示目前的记录被分割的字段的数目,NF可以理解为Number of Field。

下面以示例程序来进行说明,首先准备两个输入文件class1和class2,记录了两个班级的成绩信息,内容分别如下所示:

CodingAnts@ubuntu:~/awk$ cat class1
zhaoyun 85 87
guanyu 87 88
liubei 90 86
CodingAnts@ubuntu:~/awk$ cat class2
caocao 92 87 90
guojia 99 96 92

  现在要查看两个班级的所有成绩信息,并在每条信息前加上行号,则可以使用下面的awk指令;

CodingAnts@ubuntu:~/awk$ awk '{print NR,$0}' class1 class2
1 zhaoyun 85 87
2 guanyu 87 88
3 liubei 90 86
4 caocao 92 87 90
5 guojia 99 96 92

  这里的行号就是通过NR来实现的,awk每读取一条记录,NR的值便加一。如果要求每个班级的行号从头开始变化,则需要使用FNR来实现,如下:

CodingAnts@ubuntu:~/awk$ awk '{print FNR,$0}' class1 class2
1 zhaoyun 85 87
2 guanyu 87 88
3 liubei 90 86
1 caocao 92 87 90
2 guojia 99 96 92

  下面的示例结合awk内建变量FILENAME,显示出来的两个班级的成绩信息可以进行更好的区分;

CodingAnts@ubuntu:~/awk$ awk '{print FILENAME,"NR="NR,"FNR="FNR,"$"NF"="$NF}' class1 class2
class1 NR=1 FNR=1 $3=87
class1 NR=2 FNR=2 $3=88
class1 NR=3 FNR=3 $3=86
class2 NR=4 FNR=1 $4=90
class2 NR=5 FNR=2 $4=92

  除了NR和FNR外,上面的示例中还演示了NF的使用,class1中每行有3个字段,而class2中有4个字段,通过$NF就可以很方便的获取最后一个字段了。

原文地址:https://www.cnblogs.com/klausage/p/14828244.html