awk命令不僅僅是Linux系統的命令,也是一種編程語言,用來處理數據和生成報告(Exel),處理的數據可以是一個或多個文件(標准輸入和管道獲取標准輸入)。可在命令行上編輯操作,也可以寫成awk程序運用。
查看awk版本
# awk --version
awk格式
# awk -F “參數” ‘BEGIN{} 模式 {動作} END{}’ 文件路徑
參數
-F 指定awk按照什么符號進行文本切割,將原文件內容切割成一列一列,如果不指定-F參數,awk默認按照空格進行文本切割
{} 代表print輸出 輸出多個值用逗號“,”分隔;{}中雙引號里的內容原封不動輸出
$ 代表取列
$1 代表第一列,以此類推 $0表示所有內容 $NF表示輸出最后一列(最后一組元素)
BEGIN{}:告知awk,數據要如何讀取
END{}:告知awk,程序要如何結束
awk指令是由模式、動作,或者模式和動作的組合組成。
awk [awk參數] ‘模式 {動作}’ 文件名
模式:過濾條件
動作:執行
在指定文件中,awk先根據分隔符進行切割,再在模式中過濾所需的數據,再通過動作去執行(無動作時,默認輸出全部內容)
# awk -F “: ” ‘NR==3{print $1}’ yunjisuan.txt
awk執行過程
從BEGIN模塊開始,一行一行讀數據,看模式,是否符合條件,符合則執行動作;若不符合,則執行下一行。執行到結尾,會執行END模塊后輸出文本內容
1)awk讀入第一行內容
2)判斷是否符合模式中的條件NR>=2
a,如果匹配則執行對應的動作{print $0}
b,如果不匹配條件,繼續讀取下一行
3)繼續讀取下一行
4)重復過程1-3,直到讀取到最后一行(EOF:end of file)
分隔符
通過-F參數指定分隔符,換行符默認\n
NR這個符號的真正含義不是行號,二十數據被awk讀取一段以后,NF就會記錄一次。
由於awk默認以\n作為每次讀取數據的結束標志,NR就恰好等於行號。
awk的換行符
通過BEGIN{},在awk讀取數據之前設定它的讀入換行符、輸出換行符;通常,默認awk的讀入換行符和輸出換行符為\n
RS 是輸入記錄分隔符,決定awk如何讀取或分隔每行(記錄)
ORS表示輸出記錄分隔符,決定awk如何輸出一行(記錄)的,默認是回車換行(\n)
FS是輸入區域分隔符,決定awk讀入一行后如何再分為多個區域。
OFS表示輸出區域分隔符,決定awk輸出每個區域的時候使用什么分隔他們。
awk無比強大,你可以通過RS,FS決定awk如何讀取數據。你也可以通過修改ORS,OFS的值指定awk如何輸出數據。
更改換行符,用RS,ORS操作
RS=””讀入換行符(輸入輸出數據記錄分隔符) ORS=””輸出換行符(輸出記錄分隔符) NR 記錄行號
當更改輸出換行符時,輸出換行符會替換掉讀入換行符
因為設定了讀入換行符RS=”:”,因此,在awk的內存里的數據是按照如下排列的:
1 root
2 x
3 0
4 0
5 root
6 /root
7 /bin/bash\nbin
8 x
9 1
10 1
由於awk默認輸出換行符是\n,因此在輸出時,awk會在內存行的每行結尾附加輸出換行符號\n,因此輸出時效果如下:
1 root
2 x
3 0
4 0
5 root
6 /root
7 /bin/bash
Bin
8 x
9 1
10 1
按單詞出現頻率降序排序(計算文件中每個單詞的重復數量)
方法(1)將所有非小寫字母和非大寫字母替換成空,剩余都是英文單詞,再計數並排序
# cat count.txt | xargs -n1 | sort | uniq -c | sort -rn
引申:
sort 默認按26個字母排序(默認指定排序為第一列)
sort -n 按照數字大小排序
sort -r 倒序排序
sort -k 數字 從第“數字”列,按大小排序
uniq 相同元素去重
uniq -c 去重並計數
替換tr
# tr “” “”
tr “a-z” “A-Z” 轉換大小寫
tr “:” ”?” 把:替換成?
方法(2)將文件里面的所有空格替換為回車換行符“\n”
# cat count.txt | tr " " "\n" | sort | uniq -c | sort -rn
方法(3)grep所有連續的字母,grep -o參數讓他們排成一列
# grep -o "[a-zA-Z]\+" count.txt | sort | uniq -c | sort
awk的模式分類
(1)正則表達式模式
(2)比較表達式模式
(3)范圍模式
(4)特殊模式BEGIN和END
正則表達式模式
顯示第9列是200的行的IP地址
# awk ‘$9~/^200$/ {print $1}’ access.log
在第9列模式下,~進行正則匹配操作,以200開頭,以200結尾過濾,
打印$1,顯示IP地址
# awk ‘$9~/^404$/ {print $1}’ access.log | sort | uniq -c
在上述基礎上,排序並去重、計數
或# awk ‘$9==”404” {print $1}’ access.log | sort | uniq -c
awk不支持的正則符號“{}”,需要加--posix或--re-interval實現
x{m}
x{m,}
x{m,n}
~ b表示進行正則匹配
!~ 表示與~相反
表示以第五列匹配正則表達式,過濾含有shutdown的字符串,顯示這一行
# awk -F “:” ‘$5~/shutdown/’ yunjisuan.txt
顯示姓zhang的人的第二次捐款金額及他的名字
# awk -F “[ :]+” ‘$1~/^zhang/ {print $2,$(NF-1)}’ /server/files/reg.txt
顯示xiaoyu的姓氏和ID號碼
# awk -F “[ : ]+” ‘$2~/^xiaoyu/ {print $1,3$}’ /server/files/reg.txt
顯示所有以41開頭的ID號碼的人的全名和ID號碼
# awk -F “[ :]+” ‘$3~/~41/ {print $1,$2,$3}’ /server/files/reg.txt
顯示所有以一個D或X開頭的人名全名
# awk -F “[: ]+” ‘$2~/^d|^x/ {print $1,$2}’ /server/files/reg.txt
顯示所有ID號碼最后一位數字是1或5的人的全名
# awk -F “[ :]+” ‘$3~/1$|5$/ {print $1,$2}’ /server/files/reg.txt
顯示xiaoyu的捐款,每個值都有以$開頭,如$520$200$135
# awk -F “[ :]+” ‘$2~/xiaoyu/ {print “$”$4”$”$5”$”$6}’ /server/files/reg.txt
顯示所有人的全名,以姓、名的格式顯示,如meng,feixue
# awk -F “[ :]+” ‘{print $1”,”$2}’ /server/files/reg.txt
取網卡eth0的IP地址
默認分隔符,第一個字符前面不占位
指定分隔符,第一個字符前面占位
方法一:
# ifconfig eth0 | awk ‘BEGIN{RS=”[ :]”} NR==31’
方法二:
# ifconfig eth0 | awk -F “(addr:)|(Bcast:)” ‘NR==2{print $2}’
方法三:
# ifconfig eth0 | awk -F “[ :]+” ‘NR==2{print $4}’
# ifconfig eth0 | awk -F “[ :]” ‘NR==2{print $13}’
方法四:
# ifconfig eth0 | awk -F “[^0-9.]+” ‘NR==2{print $2}’
比較表達式模式
取出文件/etc/services的23-30行
# awk ‘NR>=23&&NR<=30’ /etc/services
# awk ‘NR>22&&NR<31’ /etc/services
判斷某一列是否等於某個字符,找出/etc/passwd中第五列是root的行
# awk -F":" '$5=="root"' /server/files/awk_equal.txt
# awk -F":" '$5~/^root$/' /server/files/awk_equal.txt
找出工資在(40000,60000)之間的員工名字
# awk -F: ‘$3>=”40000” && $3<=”60000” {print $1}’ test2
范圍模式
顯示第二行到第五行的行好和整行的內容
# awk 'NR==2,NR==5{print NR,$0}' count.txt
顯示以bin開頭,到第五行的行號及整行內容
# awk '/^bin/,NR==5{print NR,$0}' awkfile.txt
從第三列以bin開始的行到以lp開頭的行並顯示其行號和整行內容
awk -F":" '$5~/^bin/,/^lp/{print NR,$0}' awkfile.txt
從第三列以bin開頭字符串的行到第三列以lp開頭字符串的行
# awk -F: '$5~/^bin/,$5~/^lp/{print NR,$0}' awkfile.txt
BEGIN模塊
(1)定義內置變量(-F本質式修改的FS變量)
# ifconfig eth0|awk -F "(addr:)|( Bcast:)" 'NR==2{print $2}'
相當於# ifconfig eth0 | awk 'BEGIN{FS="(addr:)|( Bcast:)"} NR==2{print $2}'
# ifconfig eth0 | awk -F "[ :]+" 'NR==2{print $4}'
相當於# ifconfig eth0 | awk 'BEGIN{FS="[ :]+"}NR==2{print $4}'
# ifconfig eth0 | awk -F "[^0-9.]+" 'NR==2{print $2}'
相當於# ifconfig eth0 | awk 'BEGIN{FS="[^0-9.]+"}NR==2{print $2}'
(2)在讀取文件之前,輸出提示性信息(表頭)
# awk -F ":" 'BEGIN{print "1111","2222"} {print $1,$3} ' yunjisuan.txt
# awk -F ":" 'BEGIN{print "1111","2222"} {print $1,$3} END{print "asdf","asdfg"}' yunjisuan.txt
(3)使用BEGIN 模塊的特殊性質,進行一些測試(計算)
計算數值
# awk 'BEGIN{print 10/3}'
賦值變量
# awk 'BEGIN{a=1;b=2;print a,b,a+b}'
awk中字母會被認為是變量,給一個變量賦值字母(字符串),用雙引號
# awk 'BEGIN{abcd=123456;a=abcd;print a}'
123456
# awk 'BEGIN{a="abcd";print a}'
abcd
表示a的b次方
# awk ‘BEGIN{a=2;b=3;print a**b}’
查看/etc/services空行個數
方法一:
# grep -c “^$” /etc/services
方法二:
# awk ‘/^$/ {i=i+1} END{print i}’ /etc/services
其中,i=i+1 等同於i++
查看test文件一共有多少行
# awk ‘{i++}END{print i}’ test
求test文件每行的值之和
# awk ‘{i=i+$0}END{print i}’ test
求 test文件每行的值之積(BEGIN初始變量設定位置)
# awk ‘BEGIN{i=1}{i=i*$1}END{print i}’ test
awk數組
用一個變量表示多組數據,通常優先考慮數組,eg:變量名[數字]=不同的值
awk數組結構
arrayname[string]=value
arrayname為數組名
string為元素名
value為值
循環語句
for(變量1 in 變量2) 表示變量1在變量2 中取值,變量1被變量2循環賦值
統計域名訪問次數
(1)取出域名
(2)將域名去重
(3)統計次數
方法一:
# awk -F “/+” ‘{print $2}’ yuming | sort uniq -c
方法二:
# awk -F "[ /]+" '{h[$2]++}END{for(i in h)print i,h[i]}' yuming
統計域名訪問次數並累計流量
(1)取出域名
(2)將域名去重
(3)統計流量大小
# awk -F "[ /]+" '{h[$2]=h[$2]+$4}END{for(i in h)print i,h[i]}' yuming
第一列字母去重,並求和
# awk ‘{h[$1]+$2}END{for(i in h)print i,h[i]}’ test
WEB服務器日志文件
access.www.log
(企業應用) 分析圖片服務日志,把日志(每個圖片訪問次數*圖片大小的總和)排行,取top10,也就是計算每個url的總訪問大小
(在Web服務器日志文件中查看哪個IP地址(用戶)瀏覽本機次數,使用流量最多)
思路:用awk過濾出出現的IP地址,去重IP地址,統計其使用流量,並排序
說明:本題生產環境應用:這個功能可以用於IDC網站流量帶寬很高,然后通過分析服務器日志哪些元素占用流量過大,進而進行優化或裁剪該圖片,壓縮js等措施。