關於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被設定成非\n時,\n會成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就可以很方便的獲取最后一個字段了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM