awk:把文件逐行的讀入,以空格為預設分隔符將每行切片,切開的部分再進行各種分析處理,是一個強大的文本分析工具,在對數據分析並生成報告時很有優勢。 awk有3個不同版本: awk、nawk和gawk,未作特別說明,一般指gawk,gawk 是 AWK 的 GNU 版本。 命令格式: 變數 常見內置變 ...
awk:把文件逐行的讀入,以空格為預設分隔符將每行切片,切開的部分再進行各種分析處理,是一個強大的文本分析工具,在對數據分析並生成報告時很有優勢。
awk有3個不同版本: awk、nawk和gawk,未作特別說明,一般指gawk,gawk 是 AWK 的 GNU 版本。
- 命令格式:
awk [options] 'program' FILE ... 其中: options: -F:指明輸入時用到的欄位分隔符,預設空白字元; -v:指定變數 -v var=value:自定義變數 program: PATTERN{ ACTION STATEMENTS;...} (語句之間用 ; 分隔) PATTERN--模式,這意味著並不是對文件中的每一行進行處理,而是處理那些能夠被模式匹配到的行,不跟模式表示全文; ACTION--常見的處理機制是列印,命令有print和printf.
- 變數
- 常見內置變數
FS:切割時的分隔符,預設為空白字元; OFS:切割後輸出時的分隔符,預設為空白字元; RS:輸入時的換行符,預設為'\n'; ORS:輸出時的換行符,預設為'\n'; NF:欄位數量 ( $NF表示最後一個欄位); NR:行數; FNR:分別計算各文件的行數; FILENAME:當前文件名; ARGC:命令行參數的個數; ARGV:數組,保存的是命令行所給定的各參數 示例: awk -v FS=: '{print $1}' /etc/passwd (相當於awk -F: "{print $1}" /etc/passwd) awk -v FS=: -v OFS=, '{print $1,$2}' /etc/passwd awk -v RS=' ' '{print}' /etc/issue awk '{print NF}' /etc/fstab (可對比 awk '{print $NF}' /etc/fstab,$NF表示最後一個欄位) awk 'BEGIN{print ARGC}' /etc/fstab /etc/issue (命令行參數有3個,分別為awk,/etc/fstab,/etc/issue) awk 'BEGIN{print ARGV[#]}' /etc/fstab /etc/issue (#表示索引下標)
-
- 自定義變數
兩種方式可自定義變數:
(1) -v var=value
(2) 在program中直接定義
示例:
awk -v test="hello gawk" 'BEGIN{print test}' (相當於awk 'BEGIN{test="hello gawk";print test}')
- 列印輸出
print item1,item2,...
示例:
tail -5 /etc/fstab | awk '{print $2,$4}' ($1..$#:內置變數,表示分隔後的欄位)
tail -5 /etc/fstab | awk '{print "hello:",$2,$4}' (註意,{}只能由單引號'' 引起來,不能用雙引號"")
要點:
(1) 逗號,作為不同欄位的分隔符;
(2) item可以是字元串,數值,當前記錄的欄位、變數或awk的表達式;
(3) 如省略item,相當於print $0(列印所有元素;$0表示所有欄位)
-
- printf
格式化輸出:printf FORMAT,item1,item2,...
釋義:
(1) FORMAT必須給出;
(2) 不會自動換行,需要顯式給出換行控制符,'\n';
(3) FORMAT中需要分別為後面的每個item指定一個格式化符號;
格式符:
%c:顯示字元的ASCII碼;
%d,%i:顯示十進位整數;
%e,%E:科學計數法數值顯示;
%f:顯示為浮點數;
%g,%G:以科學計數法或浮點形式顯示數值;
%s:顯示字元串;
%u:無符號整數;
%%:顯示%自身
修飾符:
#[.#]:第一個數字控制顯示的寬度;第二個#表示小數點後的精度
示例:
%-3.1f,其中 '-' 表示左對齊;%+5.2d,其中 '+' 會顯示數值的符號
awk -F: '{printf "Uername:%s, UID:%d\n",$1,$3}' /etc/passwd
awk -F: '{printf "Uername:%-15s, UID:%d\n",$1,$3}' /etc/passwd
- 操作符
算術操作符:x+y,x-y,x*y,x/y,x^y(多少次方),x%y 賦值操作符:=,+=,-=,*=,/=,%=,^=,++,-- 比較操作符:>,>=,<,<=,!=,== 模式匹配符:~:是否匹配;!~:是否不匹配 邏輯操作符:&&,||,! 函數調用:function_name(argu1,argu2,...) 條件表達式: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 awk '!/^UUID/{print $0}' /etc/fstab awk -F: '$3>1000{print $1,$3}' /etc/passwd awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd
- PATTERN
(1) /regular expression/:僅處理被模式匹配到的行; (2) relational expression:關係表達式,為"真"時處理 ("真":結果是非0值或非空字元串); (3) line ranges:行範圍 (startline, endline 或 /pat1/, /pat2/); 註意: 此處行範圍不支持直接給出數字的格式 示例:
awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
awk -F: '/^h/,/^s/{print $1}' /etc/passwd (4) BEGIN/END模式: BEGIN{}: 僅在開始處理文件中的文本之前執行一次; END{}:僅在文本處理完成之後執行一次 示例:
head /etc/passwd | awk -F: 'BEGIN{print "username uid"}{printf "%-12s%-5s\n",$1,$3}END{printf "%10s\n","END"}'
- 控制語句
- 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
awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
awk '{if(NF>5) print $0}' /etc/fstab
df -h | awk -F% '/^\/dev/{print $1}' | awk '{if($NF>=20) print $1}'
-
- while and do while
語法:
while(condition) statement (條件"真"時進入迴圈;條件"假"時退出迴圈)
do statement while(condition) (至少執行一次迴圈體)
使用場景:
對一行內的多個欄位逐一處理時使用;對數組中的各元素逐一處理時使用.
示例:
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)>=7) {print $i,length($i)}; i++}}' /etc/grub2.cfg
-
- for
語法:
for(expr1;expr2;expr3) statement
for(variable assignment;condition;iteration process) {for-body}
示例:
awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
特殊用法:遍曆數組中的元素
語法:for(var in array) {for-body}
-
- switch
語法: switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; ...; default: statement}
-
- break and continue
break:終止迴圈
continue:中斷本次迴圈繼續下一輪
-
- next
提前結束對本行的處理而直接進入下一行; 示例: awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
- array數組
1) 關聯數組: array[index-expression] index-expression: ① 可使用任意字元串;字元串要使用雙引號; ② 如果某數組元素事先不存在,在引用時,awk會自動創建此元素,並將其值初始化為"空串" 2) 若要判斷數組中是否存在某元素,要使用"index in array"格式進行; 3) 若要遍曆數組中的每個元素,要使用for迴圈:for(var in array) {for-body} 示例: awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}' netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state){ print i,state[i]}}' awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' /var/log/httpd/access_log awk '/^UUID/{fs[$3]++}END{for(i in fs){print i,fs[i]}}' /etc/fstab awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count){print i,count[i]}}' /etc/fstab netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state){print i,state[i]}}'
- 內置函數
rand():返回0和1之間一個隨機數;
length([s]):返回指定字元串的長度;
sub(r,s,[t]):以r表示的模式來查找t所表示的字元中的匹配的內容,並將其第一次出現替換為s所表示的內容;
gsub(r,s,[t]):以r表示的模式來查找t所表示的字元中的匹配的內容,並將其所有出現均替換為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]}}'
awk '/^[[:space:]]*kernel/{i=1;while(i<=NF){if(length($i)>=7)print $i,length($i);i++}}' /etc/grub.conf