本文主要介紹了Linux中的awk命令的一些知識以及如何使用awk編程。不同於grep的查找、sed的編輯等命令,awk命令在文本處理和生成報告等地方是經常用到的一個強大命令。
awk命令主要用於文本分析。它的處理方式是讀入文本,將每行記錄以一定的分隔符(默認為空格)分割成不同的域,然後對不同的域進行各種處理與輸出。
awk命令的一個基本格式如下:
1
awk '{pattern + action}' {filenames}
無論awk命令簡單還是復雜,基本的格式如上所示。其中引號為必須,引號內代表一個awk程序。大括號非必須,括起來用於根據特定的模式對一系列指令進行分組。pattern是在數據中查找內容,支持正則匹配。action對查找出來的記錄執行相應的處理,比如打印和輸出等。
1
awk [-F 'field-separator'] 'commands' input-file(s)
其中的-F
指令是可選的,後面跟著指定的域分隔符,比如tab鍵等(默認是空格)。後面的commands
是真正的awk命令。input-file(s)
代表輸入的一個或多個文件
命令行調用方式是最經常使用的一種方式,也是本文所講的重點。
把平時所寫的shell腳本的首行#!/bin/sh
換成#!/bin/awk
。把所有的awk命令插入腳本中,通過調用腳本來執行awk命令。
把所有的awk命令插入單獨的文件中,然後通過以下命令調用awk:
1
awk -f awk-script-file input-file(s)
其中-f
指定了要調用的包含awk命令的文件。
打印當前目錄下所有的文件名和文件大小列表,以tab鍵分割:
1
ls -lh | awk '{print $5"\t"$9}'
$0變量是指當前一行記錄,$1是指第一個域數據,$2指第二個域數據……以此類推。
awk提供了print與printf兩種打印輸出的函數。
print的參數可以是變量、數值和字符串。參數用逗號分割,字符串必須用雙引號引用。
printf與C語言中的printf函數類似,可以用來格式化字符串。
1
awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
1
ll | awk -F '\t' 'print $9'
1
ls -lh | awk 'BEGIN {print "size\tfilename"} {print $5"\t"$9} END {print "---end---"}'
BEGIN...END
語句的執行流程是,awk命令讀入數據,然後從BEGIN語句開始,依次讀取每一行記錄,並打印相應的域,當所有記錄都處理後再執行END語句後的程序。也就是說BEGIN...END
語句塊中的內容在讀取數據過程中會反復執行,直到數據讀取完成。
下面的例子表示打印當前目錄下,所有以.bat後綴結尾的文件名列表:
1
ls -l | awk -F: '/\.dat$/{print $9}'
awk有許多內置變量用來設置環境變量信息,這些變量都可以被改變。常用的內置變量和作用如下所示:
1 2 3 4 5 6 7 8 9 10 11
ARGC 命令行參數個數
ARGV 命令行參數排列
ENVIRON 支持隊列中系統環境變量的使用
FILENAME awk浏覽的文件名
FNR 浏覽文件的記錄數
FS 設置輸入域分隔符,等價於命令行-F選項
NF 浏覽記錄的域的個數
NR 已讀的記錄數
OFS 輸出域分隔符
ORS 輸出記錄分隔符
RS 指定用來切片的分隔符
awk中的內置變量都是很有用處的,可以直接使用。比如上面講過的指定分隔符操作就可以用FS變量來代替:
1
ll | awk '{FS="\t";} {print $9}'
下面會有很多實用awk內置變量的例子。
awk可以自定義變量,並參與運算。
比如統計當前目錄下列出的文件總大小,以M為單位顯示出來:
1
ls -l | awk 'BEGIN {size=0;} {size+=$5;} END {print "size is ", size}'
注意此統計沒有把文件夾下的所有文件算在內。
自定義的變量有時候可以不用作初始化操作,不過正規起見,還是建議作初始化操作為好。
awk中的條件語句跟C語言類似,聲明方式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
if(expression){
statement1;
statement2;
}
if(expression){
statement1;
} else {
statement2;
}
if(expression1){
statement1;
} else if (expression2) {
statement2;
} else {
statement3;
}
看下面例子,將第三列為12,第六列為0的行打印輸出:
1
awk 'BEGIN {FS="\t"}{if($3==12 && $6==0) print $0} END' incoming_daily_20150223.dat
awk中的循環語句同樣與C語言中的類似,支持while、do/while、for、break、continue關鍵字。
看下面的例子,輸出每行的行號和第一列的數據:
1
awk 'BEGIN {FS="\t";} {data[NR] = $1} END {for(i=1; i<=NR; i++) print i"\t"data[i]}' incoming_daily_20150223.dat
看下面例子,統計第六列每一個值出現的次數:
1
awk 'BEGIN {FS="\t"}{count[$6]++} END {for(x in count) print x,count[x]}' incoming_daily_20150223.dat
Linux系統之文本格式化工具awk http://www.linuxidc.com/Linux/2016-02/128150.htm
AWK簡介及使用實例 http://www.linuxidc.com/Linux/2013-12/93519.htm
Linux awk文本分析工具 http://www.linuxidc.com/Linux/2015-12/126217.htm
Linux文本處理工具之awk http://www.linuxidc.com/Linux/2015-01/111437.htm
如何在Linux中使用awk命令 http://www.linuxidc.com/Linux/2014-10/107542.htm
文本分析工具-awk http://www.linuxidc.com/Linux/2014-12/110939.htm
使用awk格式化輸出文本 http://www.linuxidc.com/Linux/2016-04/130193.htm