awk:報告生成器,格式化文本輸出。有多種版本:New awk(nawk),GNU awk(gawk)。CentOS中使用的是gawk
gawk:模式掃描和處理語言 linux
awk程序可由:BEGIN語句塊、可以使用模式匹配的通用語句塊(program)、END語句塊,共3部分組成 pragram一般是被放在單引號中
經常使用選項:
-F "分隔符" 指明輸入時用到的字段分隔符,若是不指定分隔符,默認以空格分隔
-V var=value 變量賦值 shell
awk變量有內置和自定義變量
經常使用內置變量:
變量名 | 做用
$0 | 表示一整行 |
$1-$n | 表示第一個字段到第n個字段 |
FS | 輸入字段分隔符,默認爲空白字符 |
OFS | 輸出字段分隔符,默認爲空白字符 |
RS | 輸入記錄分隔符,指定輸入時的換行符 |
ORS | 輸出記錄分隔符,指定輸出時的換行符 |
NF | 字段數量 |
NR | 記錄號 |
FNR | 各文件分別記數,記錄號 |
FILENAME | 當前處理文件的文件名 |
ARGC|命令行參數的個數,awk算第一個參數,中間語句不算參數 |
ARGV|數組,保存的是命令午所給定的各參數|express
[root@CentOS7 data]#awk 'BEGIN{print ARGV[0] }' /etc/fstab awk [root@CentOS7 data]#awk 'BEGIN{print ARGV[1] }' /etc/fstab /etc/fstab
自定義變量(區分字符大小寫) vim
[root@CentOS7 data]#awk -v test='hello gawk' '{print test}' /etc/fstab hello gawk . . . hello gawk [root@CentOS7 data]#awk -v test='hello gawk' 'BEGIN{print test}' hello gawk [root@CentOS7 data]#awk 'BEGIN{test="hello,gawk";print test}' hello,gawk
printf命令
格式化輸出:print "FORMAT",item1,item2... 數組
一、必須指定FORMAT
二、不會自動換行,須要顯式給出換行控制符,\n
三、FORMAT中須要分別爲後面第個item指定格式符
格式符:與item一一對應
%c:顯示字符的ASCII碼
%d,%i:顯示十進制整數
%e,%E:顯示科學計數法數值
%f:顯示爲浮點數
%g,%G以科學計數法或浮點形式顯示數值
%s:顯示字符串
%u:無符號整數
%%:顯示% bash
修飾符
#[.#] 第一個數字控制顯示的寬度;第二個#表示小數點後數度,%3.1f表示顯示到小數點後一位 dom
算術操做符 tcp
+、-、*、/、^、% 加減乘除乘取餘
-x:轉換爲負數
+x:將字符串轉換爲數值 ide
字符串操做符:沒有符號的操做符,字符串鏈接
賦值操做符 函數
=,+=,-=,*=,/=,%=,^=,++,--
比較操做符
==,!=,>,>=,<,<=
模式匹配符:
~:左邊是否和右邊匹配,包含
!~: 是否不匹配
邏輯操做符:與&&,或||,非!
條件表達式(三目表達式)
selector?if-true-expression:if-false-expression
若是selector 爲真,執行if-true部分,爲假,執行if-false部分
根據模式(pattern)條件,過濾匹配的行,再作處理
若是未指定:空模式,匹配第一行
/regular expression/ :僅處理可以與模式相匹配的行,須要用//括起來
[root@CentOS7 data]#awk '/^UUID/{print $1}' /etc/fstab UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 UUID=8ea0b7b5-109d-43b7-bd1a-f18c5f4ae5de UUID=f6d8e5da-09bf-480a-9089-a83d8cb674c5 UUID=74df8071-4517-4645-872e-976e8a5514e4
表示只顯示以UUID開頭的行的第一個字段
relational expression:關係表達式,結果爲"真"纔會實處理
真:結果爲非0值,非空字符串
假:結果爲空字符串或0值line ranges:行範圍 表示從哪行開始,到哪行結束
startline,endline:/pat1/,/pat2/不支持直接給出數字格式
示例:表示從以root開始的行,到以nobody開始的行[root@CentOS7 data]#awk '/^root/,/^nobody/{print $1}' /etc/passwd root:x:0:0:root:/root:/bin/bash . . . nobody:x:99:99:Nobody:/:/sbin/nologin [root@CentOS7 data]#
BEGIN/END模式
BEGIN{}:僅在開始處理文件中的文本以前執行一次
END{}:僅在文本處理完成以後執行一次
[root@CentOS7 data]#awk -F: 'BEGIN{print "USER USERID"}{print $1 ":" $3}END{print "END FILE"}' /etc/passwd USER USERID root:0 . . . END FILE
if-else語句
語法:if(條件){statement;...}[else statement]
if(){}else if(){}else{}
使用場景:對awk取得的整行或某個字段作條件判斷
示例:顯示ID大於等於1000的行的第一,第3字段[root@CentOS7 data]#awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd nfsnobody 65534 liuqiyou 1000[root@CentOS7 data]#awk -F: '{if($NF=="/bin/bash")print $1}' /etc/passwd root liuqiyou[root@CentOS7 data]#awk -F: '{if($3>=1000) printf "Common user: %s\n",$1; else printf "root or Sysuser: %s\n",$1}' /etc/passwd root or Sysuser: root . . . root or Sysuser: tcpdump Common user: liuqiyou[root@CentOS7 data]#awk 'BEGIN{test=100;if(test>90){print "very good "}else if(test>60){print " goood"}else{print "no pass"}}' very goodwhile 循環
語法:while(條件){動做}
條件"真",進入循環;條件"假",退出循環
使用場景:
對一行內的多個字段逐一處理時使用
對數組中的各元素 逐一處理時使用
示例:[root@CentOS7 data]#awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.0-957.el7.x86_64 30 root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46 ro 2 crashkernel=auto 16 rhgb 4 quiet 5 LANG=en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-64dc0677454740549e82eabaf3619f3c 50 root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46 ro 2 crashkernel=auto 16 rhgb 4 quiet 5[root@CentOS7 data]#awk 'BEGIN{i=1;sum=0;while(i<=100){sum+=i;i++}print sum}' 5050do-while循環
語法:do{}while()
先執行一次循環體後作條件判斷,最少執行一次[root@CentOS7 data]#awk 'BEGIN{total=0;i=0;do{total+=i;i++;}while(i<=100);print total}' 5050for循環
語法:for(i=0;i<=100;i++){動做}
特殊用法:遍歷數組是的元素
for(i in array){print i,array[i]}[root@CentOS7 data]#awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.0-957.el7.x86_64 30 root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46 ro 2 crashkernel=auto 16 rhgb 4 quiet 5 LANG=en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-64dc0677454740549e82eabaf3619f3c 50 root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46 ro 2 crashkernel=auto 16 rhgb 4 quiet 5[root@CentOS7 data]#awk 'BEGIN{for(i=1;i<=100;i++)sum+=i;print sum}' 5050switch語句
語法:switch(expression){case VALUE1 or /PEGEXP/:statement1;case VALUE2 or /REGEXP2/}break和continue
break 跳出整個循環,提早結束循環[root@CentOS7 data]#awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}' 2145continue 跳出本次循環,進入下一次循環
[root@CentOS7 data]#awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}' 2500next:跳出本行循環,進入下一行循環
關聯數組:array[index-expession]
index-expession:
一、可以使用任意字符串;字符串要使用雙引號括起來
二、若是某數組元素事先不存在,在引用 時,awk會自動建立些元素,並將其值初始化爲"空串"
三、若要判斷數組中是否存在某元素,要使用"index in array"格式進行遍歷[root@CentOS7 data]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}' Monday [root@CentOS7 data]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["tue"]}' Tuesday去除重複的行
[root@CentOS7 data]#awk '{!line[$0]++;print $0,line[$0]}' /etc/passwd使用for循環遍歷數組中的每一個元素
for(var in array){for-body}
var會遍歷arrayr的每一個索引[root@CentOS7 data]#netstat -tan |awk '/^tcp/{state[$NF]++}END{for(i in state){print i,state[i]}}' LISTEN 9 ESTABLISHED 1[root@CentOS7 data]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays){print i,weekd asys[i]}}' tue mon
數值處理:
rand():返回0到1之間一個隨機數
awk 'BEGIN{STAND();for(i=1;i<=10;i++)print int(rand()*100)}'
字符串處理:
length([s]):返回指定字符串的長度
[root@CentOS7 data]#awk -F: '{print length($0)}' /etc/passwd
sub(r,s,[t]):對t字符串搜索r表示的模式匹配的內容,並所有替換爲s所表示的內容
[root@CentOS7 data]#echo "2008:08:08 08:08:08" |awk 'sub(/:/,"-",$1)' 2008-08:08 08:08:08
gsub(r,s[t]):對t字符串進行搜索r表示的模式匹配的內容,並所有替換爲s所表示的內容
[root@CentOS7 data]#echo "2008:08:08 08:08:08" |awk 'gsub(/:/,"-",$1)' 2008-08-08 08:08:08 [root@CentOS7 data]#echo "2008:08:08 08:08:08" |awk 'gsub(/:/,"-",$0)' 2008-08-08 08-08-08
split(s,array,[r]):以r爲分隔符,切割字符串s,並將切割後的結果保存到array所表示的數組中,第一個索引值爲1,第二個索引值爲2,...
[root@CentOS7 data]#netstat -tn | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}' 172.22.37.100 1
自定義函數
自定義函數格式
function name ( parameter, parameter, ... ) { statements return expression }
awk中調用shell命令
system命令
空格是awk中的字符串鏈接符,若是system中須要使用awk中的變量,可使用空格分隔,或者說除了awk的變量外其餘一概用""引用起來[root@CentOS7 data]#awk 'BEGIN{system("hostname")}' CentOS7.localdomain[root@CentOS7 data]#awk 'BEGIN{score=100;system("echo your scores is "score)}' your scores is 100
將awk程序寫成腳本,直接調用或執行
[root@CentOS7 data]#vim f1.awk #!/bin/awk {if($3>=1000)print $1,$3} [root@CentOS7 data]#awk -F: -f f1.awk /etc/passwd nfsnobody 65534 liuqiyou 1000
[root@CentOS7 data]#vim f2.awk #!/bin/awk -f #this is a awk script {if($3>=1000)print $1,$3} [root@CentOS7 data]#chmod +x f2.awk [root@CentOS7 data]#./f2.awk -F: /etc/passwd nfsnobody 65534 liuqiyou 1000
格式:awkfile var=value var2=value2...inputfile
注意:在BEGIN過程當中不可用。直到首行輸入完成之後,變量纔可用。能夠能完-v參數,讓awk在執行BEGIN以前獲得變量的值。命令行每個指定的變量都要一個-v參數
[root@CentOS7 data]#vim test.awk #!/bin/awk -f {if($3>=min && $3<=max)print $1,$3} [root@CentOS7 data]#chmod +x test.awk [root@CentOS7 data]#./test.awk -F: min=100 max=200 /etc/passwd systemd-network 192 abrt 173 rtkit 172 pulse 171 qemu 107 usbmuxd 113