awk工作原理:
第一步:執行BEGIN{action;… } 語句塊中的語句
第二步:從文件或標準輸入(stdin) 讀取一行,然後執行pattern{action;… }語句塊,它逐行掃描文件,從第一行到最後一行重複這個過程,直到文件全部被讀取完畢。
第三步:當讀至輸入流末尾時,執行END{action;…}語句塊 BEGIN 語句塊
在awk 開始從輸入流中讀取行之前被執行,這是一個可選的語句塊,比如變量初始化、打印輸出表格的表頭等語句通常可以寫在BEGIN 語句塊中
END語句塊在awk 從輸入流中讀取完所有的行之後即被執行,比如打印所有行的分析結果這類信息彙總都是在END 語句塊中完成,它也是一個可選語句塊
pattern 語句塊中的通用命令是最重要的部分,也是可選的。如果沒有提供pattern 語句塊,則默認執行{ print } ,即打印每一個讀取到的行,awk 讀取的每一行都會執行該語句塊
awk基本用法:
awk [options] 'program' var=value file… awk [options] -f programfile var=value file… awk [options] 'BEGIN{ action;… } pattern{ action;… } END{action;… }' file... 常用選項: -F 指明輸入時用到的字段分隔符(不指定則默認空白) -v var=value: (變量賦值)
awk程序(program)通常由:BEGIN語句塊、能夠使用模式匹配的通用語句塊、END 語句塊,共3部分組成,program 通常 是被單引號或雙引號中
注: 普通字符串加雙引號 變量則不用加
省略action行 ,則默認執行 print $0 的 的 操作
print格式:print item1, item2, ...
要點:
(1) 逗號分隔符
(2) 輸出的各item可以是字符串,也可以是數值;當前記錄的字段、變量或awk 的表達式
(3) 如省略item ,相當於print $0 "\t" 對齊 相當於tab鍵
常用變量:
1、 FS :輸入字段分隔符,默認爲空白字符 (可以引用,-F打到的效果和這個-FS的一樣)
awk -v FS=':' '{print $1,FS,$3}’ /etc/passwd awk –F: '{print $1,$3,$7}’ /etc/passwd
2、OFS :輸出字段分隔符,默認爲空白字符
awk -v FS=‘:’ -v OFS=‘:’ '{print $1,$3,$7}’ /etc/passwd
3、RS :指定RS等於的值爲分隔符,原換行符仍有效
awk -v RS=' ' '{print }' /etc/passwd
4、ORS :輸出記錄分隔符,輸出時用指定符號代替換行符
awk -v RS=' ' -v ORS='###' '{print }' /etc/passwd
5、NF :字段數量
awk -F: '{print NF}' /etc/fstab, 引用內置變量不用$ awk -F: '{print $(NF-1)}' /etc/passwd
6、NR :行號(記錄數)可以把兩個鏈接起來
awk '{print NR}' /etc/fstab awk 'END{print NR}' /etc/fstab
7、FNR :各文件分別計數, 行號
awk '{print FNR}' /etc/fstab /etc/inittab
8、FILENAME :當前文件名
awk 'END{print FILENAME}' /etc/fstab
9、ARGC :命令行參數的個數
awk '{print ARGC}' /etc/fstab /etc/inittab awk 'BEGIN {print ARGC}' /etc/fstab /etc/inittab
10、ARGV :數組,保存的是命令行所給定的各參數
awk 'BEGIN {print ARGV[0]}' /etc/fstab /etc/inittab awk 'BEGIN {print ARGV[1]}' /etc/fstab /etc/inittab
格式化輸出:printf “FORMAT ”, item1, item2, ...
(1) 必須指定FORMAT
(2) 不會自動換行,需要顯式給出換行控制符,\n
(3) FORMAT 中需要分別爲後面每個item 指定格式符
格式符:與item 一一對應
%c: 顯示字符的ASCII碼
%d 或 %i: 顯示十進制整數
%f:顯示爲浮點數
%g, %G :以科學計數法或浮點形式顯示數值
%s:顯示字符串
%u:無符號整數
%%: 顯示% 自身
修飾符:
#[.#]:第一個數字控制顯示的寬度;第二個#表示小數點後精度
eg:%3.1f三個字符寬度,小數精確一位
- : 左對齊(默認右對齊) eg: %-15s 十五個字符和左邊對齊
+ :顯示數值的正負符號 %+d
模式匹配符:~ :左邊是否和右邊匹配包含 !~ :是否不匹配
範例: awk –F: '$0 ~ /root/{print $1}' /etc/passwd awk '$0~“^root"' /etc/passwd awk '$0 !~ /root/‘ /etc/passwd awk –F: ‘$3==0’ /etc/passwd
BEGIN/END 模式
BEGIN{} :僅在開始處理文件中的文本之前執行一次
END{} :僅在文本處理完成之後執行一次
邏輯符:
&& 與
|| 或
! 非
PATTERN: 根據pattern 條件,過濾匹配的行,再做處理
(1) 如果未指定:空模式,匹配每一行
(2) /regular expression/ :僅處理能夠模式匹配到的行,需要用/ / 括起來,//之間可以寫正則
awk '/^UUID/{print $1}' /etc/fstab awk '!/^UUID/{print $1}' /etc/fstab
(3) relational expression: 關係表達式,結果爲“真”纔會被處理
真:結果爲非0 值,非空字符串
假:結果爲空字符串或0值
(4) 行範圍
awk -F: '10,20{print $1}' /etc/passwd
eg: awk -F: 'i=1;j=1{print i,j}' /etc/passwd awk '!0' /etc/passwd ; awk '!1' /etc/passwd awk –F: '$3>=1000{print $1,$3}' /etc/passwd awk -F: '$3<1000{print $1,$3}' /etc/passwd awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd awk -F: '$NF ~ /bash$/{print $1,$NF}' /etc/passwd
三目運算: selector ?if-true:if-false
if-else語句
語法:if(condition){statement;…}[else statement]
if(condition1){statement1}else if(condition2){statement2}else{statement3}
使用場景:對awk取得的整行或某個字段做條件判斷
示例: awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd awk '{if(NF>5) print $0}' /etc/fstab awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else{printf "root or Sysuser: %s\n",$1}}' /etc/passwd awk -F: '{if($3>=1000) printf "Common user: %s\n",$1;else printf "root or Sysuser: %s\n",$1}' /etc/passwd df -h|awk -F% '/^\/dev/{print $1}'|awk '$NF>=80{print $1,$5}' awk 'BEGIN{test=100;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'
while語句
語法:while(condition){statement;…}
條件“真”,進入循環;條件“假”, 退出循環
使用場景:對一行內的多個字段逐一類似處理時使用
對數組中的各元素逐一處理時使用
示例: awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfg awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=10){print $i,length($i)}; i++}}' /etc/grub2.cfg
for語句
語法:for(expr1;expr2;expr3) {statement;…}
awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){print $i,length(i)}}' /etc/grub2.cfg #統計文本中的單詞出現的次數
特殊用法:遍歷每個元素
for(var in array){for-body}
補充:
break [n] 退出全部
continue 退出當前
next 控制內生循環,提前結束本行,進入下一次循環
eg:awk -F: 'if($3%2!=0 next;print $1 )' /etc/passwd
數組
關聯數組:array[index-expression]
index-expression:
(1) 可使用任意字符串;字符串要使用雙引號括起來
(2) 如果某數組元素事先不存在,在引用時,awk 會自動創建此元素,並將其值初始化爲“空串”
若要判斷數組中是否存在某元素,要使用“index in array”格式進行遍歷
示例: weekdays[“mon”]="Monday“ awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}' awk '!arr[$0]++' dupfile 去重 awk '{!arr[$0]++;print $0, arr[$0]}' dupfile netstat -tan|awk '/^tcp\>/{statu[$NF]++}END{for (i in statu){print i,statu[i]}}' #統計tcp的狀態出現多少次 awk '!/^#/{print $3}' /etc/fstab |awk '{cs[$1]++}END{for(i in cs){print i,cs [i]}}' /etc/fstab #統計/etc/fstab文件中每個文件系統類型出現的次數 awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for (i in count ){print i":"count [i]}}' /etc/fstab #統計/etc/fstab文件中每個單詞出現的次數
函數
內置函數:
rand() 返回0-1之間的隨機數,注:第一次隨機,之後的重複
sub(r,s,[t]) 以r表示的模式來查找t所表示的字符內容,並將第一次出現的內容替換爲s所表示的內容
gsub(r,s,[t]) 以r表示的模式來查找t所表示的字符內容,並將出現的全部內容替換爲s所表示的內容
split(s,a[,r]) 以r爲分隔符,將切後的結果保存在a屬組中
實例:netstat -tan|awk '/^tcp\>/{print ($5,ip,":");count[ip[1]]++}END{for (i in count){print i,count[i]}}'
注:函數在我們運維過程中使用較少,所以我這裏就簡單帶過,有興趣的朋友可以去看大佬們寫的博客
http://blog.csdn.net/xiaolang85/article/details/8546744