一、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指定列分隔符
- [zhangy@localhost test]$ echo "111|222|333"|awk '{print $1}'
- 111|222|333
- [zhangy@localhost test]$ echo "111|222|333"|awk 'BEGIN{FS="|"}{print $1}'
- 111
(2)FS也可以使用正則
- [zhangy@localhost test]$ echo "111||222|333"|awk 'BEGIN{FS="[|]+"}{print $1}'
- 111
(3)FS為空時
- [zhangy@localhost test]$ echo "111|222|333"|awk 'BEGIN{FS=""}{NF++;print $0}'
- 1 1 1 | 2 2 2 | 3 3 3
(4)RS被設定成非\n時,\n會成FS分割符中的一個
- [zhangy@localhost test]$ cat test1
- 111 222
- 333 444
- 555 666
- [zhangy@localhost test]$ awk 'BEGIN{RS="444";}{print $2,$3}' test1
- 222 333
- 666
(5)OFS列輸出分隔符
- [zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $1,$2}' test1
- 111|222
- 333|444
- 555|666
- [zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $1 OFS $2}' test1
- 111|222
- 333|444
- 555|666
test1只有二列,如果100列,都寫出來太麻煩了吧。
- [zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $0}' test1
- 111 222
- 333 444
- 555 666
- [zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{NF=NF;print $0}' test1
- 111|222
- 333|444
- 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就可以很方便的獲取最后一個字段了。