Linux三劍客之awk命令詳解
awk簡單入門
awk是一個強大的文字分析工具,相對於grep的查詢,sed的編輯,awk在其對資料分析並生成報告時,顯得尤為強大。簡單來說awk就是把檔案逐行的讀入,以空格為預設分隔符將每行切片,切開的部分再進行各種分析處理。
使用方法:
awk '{pattern + action}' {filenames}
常見用法示例:
1.$1
:第一列,$0
:整行,$NF
:顯示最後一個欄位
# awk -F':' '{print $1}' /etc/passwd # 列印第一列
root
bin
...
# awk -F ':' '{print $NF}' /etc/passwd # 列印最後一列
/bin/bash
/sbin/nologin
...
2.NR
指定行號
# awk '{if (NR>=2 && NR<5 ) print $0}' /etc/passwd # 顯示2到4行
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
3.-F
指定分隔符,可指定一個或多個(預設空格);+
:把多個連續的分隔符變為一個
# ifconfig eth0|awk -F '[ :]+' 'NR==2 {print $4}' #獲取eth0 ip地址
192.168.0.135
printf命令
格式:printf format, item1, item2, ...
要點:
- 1、其與print命令的最大不同是,printf需要指定format;
- 2、format用於指定後面的每個item的輸出格式;
- 3、printf語句不會自動列印換行符;\n
format格式的指示符都以%
開頭,後跟一個字元;如下:
%c: 顯示字元的ASCII碼;
%d, %i:十進位制整數;
%e, %E:科學計數法顯示數值;
%f: 顯示浮點數;
%g, %G: 以科學計數法的格式或浮點數的格式顯示數值;
%s : 顯示字串;
%u: 無符號整數;
%%: 顯示%自身;
修飾符:
N: 顯示寬度;
-: 左對齊;
+:顯示數值符號;
示例:
# awk -F: '{printf "%-15s %i\n",$1,$3}' /etc/passwd
root 0
bin 1
daemon 2
adm 3
模式&動作
awk中每一個語句(statements)都由兩部分組成:模式(pattern
)和相應的動作(actions
)。只要模式匹配,awk就會執行相應的動作。動作部分由一個或多個命令、函式、表示式組成,之間由換行符或分號隔開,並位於大括號內。
常見的模式型別:
1、Regexp:
正則表示式,格式為/regular expression/
# awk -F: '/^r/ {print $1}' /etc/passwd
root
2、expresssion:
表示式,其值非0或為非空字元時滿足條件,
如:$1 ~ /foo/
或 $1 == "str"
,用運算子~(匹配)和!~(不匹配)
。
awk -F: '$3>=500 {print $1,$3}' /etc/passwd
awk -F: '$7~/bash$/ {print $1,$7}' /etc/passwd
awk -F: '$7!~/bash$/ {print $1,$7}' /etc/passwd
3、Ranges:
指定的匹配範圍,格式為pat1,pat2
# awk -F: '/^r/,$7~/nologin/ {print $1,$7}' /etc/passwd
root /bin/bash
bin /sbin/nologin
4、BEGIN/END:
特殊模式,僅在awk命令執行前執行一次或結束前執行一次
# awk -F: 'BEGIN{print "username id bash"} {printf "%-15s%-5s%-20s\n",$1,$3,$7}' /etc/passwd
username id bash
root 0 /bin/bash
bin 1 /sbin/nologin
daemon 2 /sbin/nologin
......
# awk '{count++;print $0;} END{print "user count is ",count}' /etc/passwd # 統計/etc/passwd的賬戶人數
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
......
user count is 34
# ll |awk 'BEGIN {size=0;} {size=size+$5;} END{print "size is ",size}' # 統計某個資料夾下的檔案佔用的位元組數:
# ll |awk 'BEGIN {size=0;} {size=size+$5;} END{print "size is ",size/1024/1024,"M"}'
5、Empty(空模式):
匹配任意輸入行;
常見的Action:
- 變數或陣列賦值
- 輸入/輸出語句
- 內建函式和自定義函式
- 流程控制語句
控制語句
1.if-else
語法:if (condition) {then-body} else {[ else-body ]}
awk -F: '{if ($1=="root") print $1, "Admin"; else print $1, "Common User"}' /etc/passwd
awk -F: '{if ($1=="root") printf "%-15s: %s\n", $1,"Admin"; else printf "%-15s: %s\n", $1, "Common User"}' /etc/passwd
awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd
2.while
語法:while (condition){statement1; statment2; ...}
awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd
awk -F: '{i=1;while (i<=NF) { if (length($i)>=4) {print $i}; i++ }}' /etc/passwd
3.do-while
語法:do {statement1, statement2, ...} while (condition)
awk -F: '{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd
4.for
語法:for ( variable assignment; condition; iteration process) { statement1, statement2, ...}
awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd
awk -F: '{for(i=1;i<=NF;i++) { if (length($i)>=4) {print $i}}}' /etc/passwd
for迴圈還可以用來遍歷陣列元素:
語法: for (i in array) {statement1, statement2, ...}
awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd
awk陣列
array[index-expression]
index-expression
可以使用任意字串;需要注意的是,如果某資料組元素事先不存在,那麼在引用其時,awk會自動建立此元素並初始化為空串;因此,要判斷某資料組中是否存在某元素,需要使用index in array
的方式。
要遍歷陣列中的每一個元素,需要使用如下的特殊結構:for (var in array) { statement1, ... }
其中,var用於引用陣列下標,而不是元素值;
netstat -an | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
# 每出現一被/^tcp/模式匹配到的行,陣列S[$NF]就加1,NF為當前匹配到的行的最後一個欄位,此處用其值做為陣列S的元素索引;
陣列的典型應用:
1.檢視TCP連線狀態
netstat -na |awk '/^tcp/ {print $6}'|sort|uniq -c|sort -rn
netstat -an|awk '/^tcp/{++s[$NF]}END{for(a in s)print a,s[a]}'
2.分析圖片服務日誌,把日誌(每個圖片訪問次數*圖片大小的總和)排行,取top10,也就是計算每個url的總訪問大小
awk '{array_num[$7]++;array_size[$7]+=$10} END{for(x in array_num){print array_size[x],array_num[x],x}}' access.log |sort -rn