awk簡介
awk是一種編程語言,也可以說是一個腳本語言解釋器,主要是用來實現文本的格式化輸出。awk是取了其三位作者名字的首字母,即Aho
,Weinberger
和Kernighan
。awk在Linux上是基于GNU協議實現的,即GNU awk,也就是gawk。
awk的工作模式
遍歷整個文件,從第一行到最后一行。每次僅讀取文件的一行,依照用戶指定的輸入分隔符進行切片,并將每個分片在awk的內存空間賦予一個內建變量(位置變量)進行保存,然后根據用戶指定的pattern尋找匹配特定模式的行,執行處理過程。
awk基本語法格式
gawk [OPTIONS] 'PATTERN{ACTION_STATEMENTS}' FILE...
-
NOTE
-
PATTERN可以是BEGIN、END、表達式等;
-
PATTERN省略則表示匹配所有數據;
-
ACTION_STATEMENT語句之間使用分號分隔;
-
默認的ACTION是print。
OPTIONS
-
-F fs,–field-separator fs:指明以fs作為輸入行的字段分隔符,默認分隔符為空格;
-
-v var=val,–assign var=val:自定義一個變量;
-
-f program-file,–file program-file:指明從指定的腳本文件中讀取awk指令。
變量
內建變量
FS:input Field Separator,輸入的字段分隔符,默認為空格; OFS:Output Field Separator,輸出的字段分隔符,默認為空格; RS:input Record Separator,輸入時的換行符,默認為\n; ORS:Output Record Separator,輸出時的換行符,,默認為\n; NF:Number of Field,當前行的字段數量; NR:Number of Record,輸入流的當前記錄編號(行數); FNR:當前輸入文檔的當前記錄編號,多個輸入文檔時有用; FILENAME:當前輸入文件名; ARGC:命令行參數的個數; ARGV:一個數組,保存命令行所給定的各參數。
實例
指明輸入的字段分隔符:
# awk -F: '{print $1,$3}' /etc/passwd -->//指定的字段分隔符可以使用引號引起,也可以不用(空格除外),引號可以是單雙引號; # awk -v FS=':' '{print $1,$3}' /etc/passwd -->//指定的字段分隔符可以使用引號引起,也可以不用(空格除外),引號可以是單雙引號; # awk 'BEGIN{FS=":"}{print $1,$3}' /etc/passwd -->//指定的字段分隔符只能使用雙引號引起。
NOTE: 指明多個分隔符時使用[],如FS="[:,]"。
自定義變量
-
變量名區分字母大小寫;
-
可以在ACTION_STATEMENT中定義;
-
可以在命令行中通過-v選項定義。
實例
# awk -v test='hello gawk' 'BEGIN{print test}' -->//指明變量值時可以使用單雙引號; # awk 'BEGIN{test="hello gawk";print test}' -->//指明變量值時只能用雙引號。
NOTE
在引用變量時不要加$
符號。
print命令
print item1,item2...
-
NOTE
-
以逗號作為分隔符;
-
輸出的各item可以是字符串、數值,也可以是當前記錄的字段、變量或awk的表達式;
-
如果省略item,相當于print $0。
printf命令:格式化輸出
printf FORMAT, item1, item2, ...
-
NOTE
-
FORMAT必須給出;
-
不會自動換行,必須顯式給出換行控制符\n;
-
FORMAT中需要分別為后面的每個item指定一個格式化符號。
格式符
%c: 顯示字符的ASCII碼; %d, %i: 顯示十進制整數; %e, %E: 科學計數法數值顯示; %f:顯示為浮點數; %g, %G:以科學計數法或浮點形式顯示數值; %s:顯示字符串; %u:無符號整數; %%: 顯示%自身;
修飾符
#[.#]:第一個數字#控制顯示寬度;第二個數字#表示小數點后邊的精度;例如,%3.3f。 +:顯示數值的符號 -:左對齊
實例
# awk -F: '{printf "username:%-15s uid:%d\n",$1,$3}' /etc/passwd
操作符
算數操作符
+:加 -:減 *:乘 /:除 %:取余 ^:冪運算
字符串操作符:沒有符號的操作符,字符串連接
賦值操作符
=:直接賦值 +=:相加后賦值給變量 -=:相減后賦值給變量 *=:相乘后賦值給變量 /=:相除后賦值給變量 ++:自加 --:自減
比較操作符
>:大于 <:小于 >=:大于等于 <=:小于等于 ==:等于 !=:不等于
模式匹配
~:匹配 !~:不匹配
邏輯操作符
&&:與 ||:或 !:非
函數調用
function_name(argu1,argu2,...)
實例
# awk 'BEGIN{print rand()}'
條件表達式
selector?if_true_expression:if_false_expression
實例
# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
PATTERN
-
empty:空模式,匹配每一行;
-
/regular expression/:僅處理能被此處模式匹配到的行,對模式取反在其之前加
!
; -
Relational Expression:關系表達式,結果有“真”有“假”,結果為“真”時才會被處理;
-
真:結果為非0值,非空字符串
-
line range:行范圍
-
startline,stopline: /par1/,/par2/
-
注意:不支持直接給出數字格式
-
實例:
# awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
-
BEGIN/END模式
-
BEGIN{}:僅在開始處理文本前執行一次
-
END{}:僅在文本處理結束后執行一次
控制語句
if(condition) {statments} if(condition) {statments} else {statements} while(conditon) {statments} do {statements} while(condition) for(expr1;expr2;expr3) {statements} break continue delete array[index] delete array exit { statements }
注意:
-
多個語句之間需用分號分隔;
-
語句之間可實現嵌套,但是需用花括號進行約束;
-
單個語句時可省略花括號。
if-else
語法:
if(condition) statement [else {statement}]
使用場景:對awk取得的整行或某個字段做條件判斷。
實例
# awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
while
語法
while(condition) statement
使用場景:對一行內的多個字段逐一類似操作時使用,對數組中的各元素逐一處理時使用。
實例
# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {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和continue
break:跳出循環
continue:提前結束本輪循環跳轉到下一輪,即完成行中的字段間跳轉
next:提前結束對本行的處理而直接進入下一行
實例
# awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
array
關聯數組:array[index-expression]
對于index-expression
需要注意:
-
可使用任意字符串,但是需要用雙引號;
-
如果數組元素事先不存在,在引用時,awk會自動創建此元素,并將其值初始化為“空串”。
實例
練習1:統計/etc/fstab文件中每個文件系統類型出現的次數; ~]# awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab 練習2:統計指定文件中每個單詞出現的次數; ~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(j in count) {print j,count[j]}}' /etc/fstab
內置函數
數值處理
-
rand():返回0和1之間的一個隨機數,但是一旦返回該值,再次請求時其值不再改變
字符串處理
-
length([s]):返回指定字符串的長度;
-
split(s,a[,r]):以r為分隔符切割字符s,并將切割后的結果保存至a所表示的數組中;
實例
# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'
原創文章,作者:Jeason,如若轉載,請注明出處:http://www.www58058.com/58288