1. 程式人生 > >Linux三劍客之awk命令詳解

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