1. 程式人生 > 其它 >Linux三劍客命令—awk

Linux三劍客命令—awk

一、概念說明

官方概念說明:

gawk - pattern scanning and processing language
模式掃描和處理檔案語言

AWK 是一種處理文字檔案的語言,主要是用來格式化文字,是一個強大的文字分析工具。

之所以叫 AWK 是因為其取了三位創始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字元。

二、awk功能應用說明

  • 處理檔案資訊

    • 文字檔案資訊
    • 日誌檔案資訊
    • 配置檔案資訊
  • 處理檔案方式

    • 排除資訊
    • 查詢資訊
    • 統計資訊
    • 替換資訊

三、awk語法原理

3.1 命令語法格式

  • 標準格式:

    awk [選項] '模式{動作}' [檔案資訊]
    awk [引數] [處理規則] [操作物件]
    
    引數:
    	-F : 指定文字分隔符(預設是以空格作為分隔符)
    	
    eg:列印系統所有使用者的解析器
    	awk -F: '{print $NF}' /etc/passwd
    
  • 模式說明(匹配資訊):

    • 普通模式(定位)

      1. 正則表示式模式

        eg: 列印以root開頭的行 
        	[root@localhost ~]# awk -F: '/^root/{print $0}' /etc/passwd
        
      2. 比較表示式模式

        相關符號:
        	>
        	<
        	>=
        	<=
        	~	:正則匹配
        	!~   :正則匹配(取反)
        
        
        eg:要求列印屬組ID大於屬主ID的行
        	[root@localhost ~]# awk -F: '$4 > $3{print $0}' /etc/passwd
        		
        eg:結尾包含bash
        	[root@localhost ~]# awk -F: '$NF ~ /bash/{print $0}' /etc/passwd
        		
        eg:結尾不包含bash
        	[root@localhost ~]# awk -F: '$NF !~ /bash/{print $0}' /etc/passwd	
        
      3. 邏輯表示式模式

        相關符號:
        	&&	: 邏輯與
        	||  :邏輯或
        	!	:邏輯非
        
        eg:要求屬組 + 屬主的ID 大於 2000 並且屬組 * 屬主的ID 大於 2000
        	[root@localhost ~]# awk -F: '$3 + $4 > 2000 && $3 * $4 > 2000{print $0}' /etc/passwd
        eg:要求屬組 + 屬主的ID 大於 2000 或者屬組 * 屬主的ID 大於 2000
        	[root@localhost ~]# awk -F: '$3 + $4 > 2000 || $3 * $4 > 2000{print $0}' /etc/passwd
        eg:要求屬組 + 屬主的ID 不大於 2000 (小於等於2000)
        	[root@localhost ~]# awk -F: '!($3 + $4 > 2000){print $0}' /etc/passwd
        
      4. 算術表示式模式

        相關符號:
        	+
        	-
        	*
        	/
        	%
        
        eg:要求屬組 + 屬主的ID 大於 2000
        	[root@localhost ~]# awk -F: '$3 + $4 > 2000{print $0}' /etc/passwd
        eg:要求屬組 * 屬主的ID 大於 2000
        	[root@localhost ~]# awk -F: '$3 * $4 > 2000{print $0}' /etc/passwd
        eg:要求列印偶數行
        	[root@localhost ~]# awk -F: 'NR % 2 == 0{print $0}' /etc/passwd
        eg:要求列印奇數行
        	[root@localhost ~]# awk -F: 'NR % 2 == 1{print $0}' /etc/passwd
        
      5. 條件表示式模式

        相關符號:
        	==
        	>
        	<
        	>=
        	<=
        	
        eg:要求列印第三行
        	[root@localhost ~]# awk -F: 'NR == 3{print $0}' /etc/passwd
        
      6. 範圍表示式模式

        eg:列印以root開頭到以ftp開頭的行
        	[root@localhost ~]# awk -F: '/^root/,/^ftp/{print $0}' /etc/passwd
        
    • 特殊模式

      • BEGIN{}

        概念說明:括號裡面的內容會在awk讀取檔案之前執行

        awk 'BEGIN{print "oldboy"}{print $0}' reg.txt 
        

        作用說明:

        用於測試
        用於計算
        修改內建變數
        
      • END{}

        概念說明:括號裡面的內容會在awk讀取檔案之後執行

        awk '{print $0}END{print "end of file"}' reg.txt  
        

        作用說明:

        顯示計算最終結果
        用於計算
        
  • 內建變數

    $0	: 代表當前行
    	[root@localhost ~]# awk -F: '{print $0, "---"}' /etc/passwd
    	
    $n	:代表第n列
    	[root@localhost ~]# awk -F: '{print $1}' /etc/passwd	
    	
    NF  :記錄當前行的欄位數(表示每一行有多少列)
    	[root@localhost ~]# awk -F: '{print NF}' /etc/passwd
    	[root@localhost ~]# awk -F: '{print $NF}' /etc/passwd
    	
    NR	:用來表示行號資訊
    	[root@localhost ~]# awk -F: '{print NR}' /etc/passwd
    	
    FS  :指定文字內容分隔符(預設是空格)
    	[root@localhost ~]# awk 'BEGIN{FS=":"}{print $NF, $1}' /etc/passwd
    
    OFS :指定列印分隔符(預設空格)
    	[root@localhost ~]# awk -F: 'BEGIN{OFS=" >>> "}{print $NF, $1}' /etc/passwd
    

    FS 的優先順序要高於 -F:-F ":" ==>BEGIN{FS=":"} ==> -vFS=":"

3.2 命令執行過程

grep、sed和awk都是讀一行處理一行,直至處理完成。

awk的生命週期如下:

  1. 接收一行作為輸入;
  2. 把剛剛讀入進來得到的文字進行分解;
  3. 使用處理規則處理文字;
  4. 輸入一行,賦值給$0,直至處理完成;
  5. 把處理完成之後的所有的資料交給END{}來再次處理;

四、awk實踐操作

4.1 實踐環境建立

cat >>./reg.txt<<EOF
Zhang Dandan 41117397 :250:100:175
Zhang Xiaoyu 390320151 :155:90:201
Meng Feixue 80042789 :250:60:50
Wu Waiwai 70271111 :250:80:75
Liu Bingbing 41117483 :250:100:175
Wang Xiaoai 3515064655 :50:95:135
Zi Gege 1986787350 :250:168:200
Li Youjiu 918391635 :175:75:300
Lao Nanhai 918391635 :250:100:175
EOF

4.2 命令操作實踐

  • 查詢實踐

    查詢實踐引數:

    指定列的分隔符號(引數): -F ""
    顯示指定行號資訊(模式): NR==
    顯示指定列的資訊(動作): print 
    

    案例說明:

    按行查詢檔案資料資訊:
    	awk 'NR==1' reg.txt
    	awk  '/250/' reg.txt
    	
    
    按行按列查詢檔案資訊:
    	awk -F':' 'NR==1{print $1}' reg.txt
    	awk -F':' 'NR==1{print $1,$2}' reg.txt
    	awk -F':' '$3~/0+/' reg.txt
    

    ~ 在awk中表示匹配或者包含什麼資訊;

    !~ 在awk中表示不匹配或者不包含什麼資訊;

  • 查詢測驗(顯示指定行的指定列的資訊)

    1. 顯示xiaoyu的姓氏和ID號碼

      條件是什麼: 找出第二列包含xiaoyu的資訊
      動作是什麼: 顯示xiaoyu這行指定列資訊
      實踐操作: 
      	awk '$2~/Xiaoyu/{print $1,$3}' reg.txt
      
    2. 姓氏是zhang的人,顯示他的第二次捐款金額及他的名字

      條件是什麼: 找出第一列包含zhang的資訊
      動作是什麼: 顯示zhang這行指定列資訊
      實踐操作: 
      	awk -F '[ :]+' '$1~/Zhang/{print $1 $2,$5}' reg.txt
      	awk -F '[ :]+' '$1~/Zhang/{print $1 $2,$(NF-1)}' reg.txt 
      
    3. 顯示所有以41開頭的ID號碼的人的全名和ID號碼

      條件是什麼: 顯示以41開頭的ID號
      動作是什麼: 顯示41開頭號碼,人的全名的對應列
      實踐操作: 
      	awk '$3~/^41/{print $1 $2,$3}' reg.txt
      
    4. 顯示所有ID號碼最後一位數字是1或5的人的全名

      條件是什麼: 以1或5結尾的ID號碼
      動作是什麼: 顯示人的全名對應列
      實踐操作: 
      	awk '$3~/[15]$/{print $1 $2}' reg.txt 
      	awk '$3~/(1|5)$/{print $1 $2}' reg.txt 
      	awk '$3~/1$|5$/{print $1 $2}' reg.txt 
      
    5. 顯示Xiaoyu的捐款資訊,並以$開頭, 如:$110$220$330

      條件是什麼: 找出xiaoyu的資訊
      動作是什麼: 顯示捐款資訊,在數值前賦予$
      實踐操作: 
      	awk '$2~/Xiaoyu/{gsub(/:/,"$",$NF);print $0}' reg.txt
      

      gsub 是一個函式。

  • 特殊模式應用案例

    1. 統計/etc/services檔案中空行數量

      grep應用:
      	grep '^$' /etc/services|wc -l
      	grep -c '^$' /etc/services
      	
      awk應用:
      	awk '/^$/{i++}END{print i}' /etc/services  (表示前面先計算,最後通過END將結果進行顯示)
      
    2. 統計/etc/passwd檔案中有多少個虛擬使用者

      awk '/nologin$/{i++}END{print i}' /etc/passwd
      
    3. 統計檔案中的數值的和

      seq 10|awk '{sum=sum+$0}END{print sum}'
      

五、awk相關擴充套件

4.1 awk中的函式

print	: 列印
printf	:格式化列印
	%s	: 字串
	%d	:數字
	-   :左對齊
	+   :右對齊
	15(任意數字)  : 至少佔用15字元
	
eg:	
	[root@localhost ~]# awk -F: 'BEGIN{OFS=" | "}{printf "|%-15s|%-15s|\n", $NF,$1}' /etc/passwd

4.2 awk中的流程控制(只存在迴圈之中)

if: 
	if(){}
	if(){}else{}
	if(){}else if(){}else{}	
		
eg:
	[root@localhost ~]# awk -F: '{if($3>$4){print "大於"}else{print "小於或等於"}}' /etc/passwd
			
			
for: 
	for(i="初始值";條件判斷;遊標){}	
 	
 eg:
 	[root@localhost ~]# awk -F: '{for(i=10;i>0;i--){print $0}}' /etc/passwd
		
		
while: 
	while(條件判斷){}

eg:
	[root@localhost ~]# awk -F: '{i=1; while(i<10){print $0, i++}}' /etc/passwd
	

4.3 awk陣列詳述

  • 陣列知識學習準備

    統計計算方法說明:

    i=i+1 :
    先計算右邊,將右邊數值給左邊變數
    i=0 i=0+1 i=1+1    (統計次數)
    
    eg:
    	awk '/^$/{i=i+1;print i}' /etc/services
    	awk '/^$/{i++;print i}' /etc/services
    	
    	
    i=i+$0 : 表示對每行的數字進行累加求和運算
    i=0 i=0+$0 i=$0(上一行)+$0(當前行)  (求和運算)
    
    eg:
    	seq 10|awk '{sum=sum+$n;print $n,sum}'  
    
  • 陣列概念知識說明

    陣列形式說明:

    hotel[110]="張三" :
    hotel		陣列名稱
    [110]		陣列元素
    "張三"     元素內容
    

    陣列實際應用:

    awk 'BEGIN{h[110]="UFO";h[114]="XO";print h[110],h[114]}'
    ...