1、awk變量
- 內(nèi)置變量
FS(field separate):輸入字段分隔符,默認(rèn)為空白字符
OFS(output field separate):輸出字段分隔符,默認(rèn)為空白字符
RS(record separate):輸入記錄分隔符,默認(rèn)為回車換行
ORS:輸出記錄的分隔符,默認(rèn)為回車換行
NF(number field ):字段數(shù)量,列的數(shù)量
NR(number record):記錄的數(shù)量,可以用于打印行號
FNR:各文件分別記錄行號
awk '{print FNR}' /etc/fstab /etc/inittab
FILENAME:當(dāng)前文件名
ARGC:命令行參數(shù)的個數(shù)
ARGV:數(shù)組,保存的是命令行所給定的各參數(shù)
[root@centos6 yum.repos.d]#awk 'BEGIN{print ARGC,ARGV[0]}' /etc/fstab /etc/issue ---awk是參數(shù)
3 awk
[root@centos6 yum.repos.d]#awk 'BEGIN{print ARGC,ARGV[1]}' /etc/fstab /etc/issue ---/etc/fstab是參數(shù)
3 /etc/fstab
[root@centos6 yum.repos.d]#awk 'BEGIN{print ARGC,ARGV[2]}' /etc/fstab /etc/issue ---/etc/issue是參數(shù)
3 /etc/issue
- 自定義變量
(1) -v var=value
(2) 在program中直接定義
[root@centos6 yum.repos.d]#awk -v test="hello gawk" 'BEGIN{print test}'
hello gawk
總結(jié):awk中的變量引用都不用$,這里和shell里的變量引用不一樣,一定要注意,并且awk中的字符串一定要加雙引號,否則會把其當(dāng)變量。
2、printf命令
?格式化輸出:printf "FORMAT", item1, item2, ...
(1) 必須指定FORMAT
(2) 不會自動換行,需要顯式給出換行控制符,\n
(3) FORMAT中需要分別為后面每個item指定格式符
?格式符:與item一一對應(yīng)
%c: 顯示字符的ASCII碼
%d, %i: 顯示十進(jìn)制整數(shù) ---比較常用
%e, %E:顯示科學(xué)計數(shù)法數(shù)值
%f:顯示為浮點(diǎn)數(shù) ----比較常用
%g, %G:以科學(xué)計數(shù)法或浮點(diǎn)形式顯示數(shù)值
%s:顯示字符串 ---最常用
%u:無符號整數(shù)
%%: 顯示%自身
?修飾符:
%3.1f:3表示控制后面要打印內(nèi)容的寬度;1表示小數(shù)點(diǎn)后精度
-: 左對齊(默認(rèn)右對齊)%-15s,15是定義寬度,表示要打印的列占據(jù)15個字符,-是定義左對齊
+:顯示數(shù)值的正負(fù)符號%+d
示例
[root@centos6 yum.repos.d]#cat /etc/fstab
/dev/sda1 /boot ext4 defaults 0 0
/dev/sda2 / ext4 defaults 0 0
/dev/sda3 /app ext4 defaults 0 0
[root@centos6 yum.repos.d]#awk '{printf "%s",$1}' /etc/fstab ---默認(rèn)
沒有換行符
/dev/sda1/dev/sda2/dev/sda3
[root@centos6 yum.repos.d]#awk '{printf "%s\n",$1}' /etc/fstab ---要
想換行加上\n
/dev/sda1
/dev/sda2
/dev/sda3
[root@centos6 yum.repos.d]#awk -F: '{printf "%-10s %-10d\n",$1,$3}' /etc/passwd ---可以實(shí)現(xiàn)左對齊
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail
[root@centos6 yum.repos.d]#awk -F: '{printf "username:%s uid:%d\n",$1,$3}' /etc/passwd
----pritf雙引號里面的內(nèi)容規(guī)定了后面要打印內(nèi)容的格式,并且是一一
對應(yīng)的關(guān)系,"username:%s 對應(yīng)的是$1的格式,uid:%d對應(yīng)的是
$3的格式
username:root uid:0
username:bin uid:1
username:daemon uid:2
username:adm uid:3
username:lp uid:4
[root@centos6 yum.repos.d]#awk -F: '{printf "username: %-15s uid: %d\n",$1,$3}' /etc/passwd
username: root uid: 0
username: bin uid: 1
username: daemon uid: 2
username: adm uid: 3
username: lp uid: 4
3、算術(shù)操作符
?算術(shù)操作符:
x+y, x-y, x*y, x/y, x^y, x%y
-x: 轉(zhuǎn)換為負(fù)數(shù)
+x: 轉(zhuǎn)換為數(shù)值
?賦值操作符:
=, +=, -=, *=, /=, %=, ^=
++, --
?比較操作符:
==, !=,>, >=, <, <=
?模式匹配符:~:左邊是否和右邊匹配包含
!~:是否不匹配
?邏輯操作符:與&&,或||,非!
示例
[root@centos6 yum.repos.d]#awk 'BEGIN{print i++}' ---在awk里i不賦值也可以,默認(rèn)情況下i=0
0
[root@centos6 yum.repos.d]#awk 'BEGIN{print ++i}' ---先相加再賦值
1
[root@centos6 yum.repos.d]#df|awk '$0 ~ /^\/dev\/sd/ {print $1,$5}'
/dev/sda2 3%
/dev/sda1 4%
/dev/sda3 1%
[root@centos6 yum.repos.d]#df |awk '$0~ "^/dev/sd" {print $1,$5}'
/dev/sda2 3%
/dev/sda1 4%
/dev/sda3 1%
[root@centos6 yum.repos.d]#awk -F: '$0 ~ "root"{print $0}' /etc/passwd
---表示整行是否包含root,如果包含就打印這一行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@centos6 yum.repos.d]#awk -F: '$0 ~ "^root"' /etc/passwd
---這里沒有寫action,也就是{}里面的內(nèi)容,默認(rèn)就是打印整行
[root@centos6 yum.repos.d]#awk '$0 !~ "root"' /etc/passwd
---表示不包含root就打印
[root@centos6 yum.repos.d]#awk -F: '$3==0' /etc/passwd
root:x:0:0:root:/root:/bin/bash
表示第三列的值是0就打印整行
[root@centos6 yum.repos.d]#awk -F: '$3>=0 && $3<=500{printf "systemuser:%s\n",$1}' /etc/passwd ---與的關(guān)系
systemuser:root
systemuser:bin
systemuser:daemon
systemuser:adm
[root@centos6 yum.repos.d]#awk -F: '$3==0 || $3 >=1000 {print $1}' /etc/passwd ---或的關(guān)系
root
nfsnobody
[root@centos6 yum.repos.d]#awk -F: '!($3==0){print $1}'
/etc/passwd ---非,注意($3==0)一定要用括號擴(kuò)起來
bin
daemon
adm
lp
- 三目表達(dá)式
selector?if-true-expression:if-false-expression
示例
[root@centos6 yum.repos.d]#awk -F: '{$3>=500?usertype="common user":usertype="sysuser or rootuser";printf "%s %s\n",usertype,$1}' /etc/passwd
[root@centos6 yum.repos.d]#awk -F: '$3>=500?usertype="common user":usertype="sysuser or rootuser"{printf "%s %s\n",usertype,$1}' /etc/passwd
這兩種寫法都可以,三目表達(dá)式可以放到大括號里面,也可以放到外面。
4、awk的pattern
PATTERN:根據(jù)pattern條件,過濾匹配的行,再做處理
(1)如果未指定:空模式,匹配每一行
(2) /regular expression/:僅處理能夠模式匹配到的行,需要用/ /括起來
awk '/^UUID/{print $1}' /etc/fstab
awk '!/^UUID/{print $1}' /etc/fstab
(3) relational expression: 關(guān)系表達(dá)式,結(jié)果為“真”才會被處理
真:結(jié)果為非0值,非空字符串
假:結(jié)果為空字符串或0值
[root@centos6 yum.repos.d]#awk '!0' /etc/issue
---結(jié)果為非0,打印
CentOS release 6.9 (Final)
Kernel \r on an \m
[root@centos6 yum.repos.d]#awk '" "' /etc/issue
---空也打印
CentOS release 6.9 (Final)
Kernel \r on an \m
[root@centos6 yum.repos.d]#awk '!1' /etc/issue
結(jié)果為0就不打印
[root@centos6 yum.repos.d]#awk '""' /etc/issue
結(jié)果為空字符串也不打印
(4) line ranges:行范圍
startline,endline:/pat1/,/pat2/不支持直接給出數(shù)字格式
awk -F: '/^root\>/,/^nobody\>/{print $1}' /etc/passwd
awk-F: '(NR>=10&&NR<=20){print NR,$1}' /etc/passwd
(5) BEGIN/END模式
BEGIN{}: 僅在開始處理文件中的文本之前執(zhí)行一次
END{}:僅在文本處理完成之后執(zhí)行一次
示例
[root@centos6 yum.repos.d]#awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
root /bin/bash
dufu /bin/bash
[root@centos6 yum.repos.d]#awk -F: '$NF ~ "bash$"{print $1,$NF}' /etc/passwd
root /bin/bash
dufu /bin/bash
[root@centos6 yum.repos.d]#awk -F: 'BEGIN{print "user uid\n------------------------------"}{printf "%-15s| %-10d\n",$1,$3}END{print "-----------------------\nend file"}' /etc/passwd
user uid
------------------------------
root | 0
bin | 1
daemon | 2
adm | 3
lp | 4
sync | 5
shutdown | 6
halt | 7
mail | 8
uucp | 10
operator | 11
games | 12
gopher | 13
ftp | 14
nobody | 99
vcsa | 69
saslauth | 499
postfix | 89
sshd | 74
dufu | 500
ntp | 38
tcpdump | 72
apache | 48
rpc | 32
dbus | 81
rpcuser | 29
nfsnobody | 65534
-----------------------
end file
[root@centos6 yum.repos.d]#seq 10|awk '++i'
1
2
3
4
5
6
7
8
9
10
[root@centos6 yum.repos.d]#seq 10|awk 'i++' 第一行時i=0,所以不打印
2
3
4
5
6
7
8
9
10
[root@centos6 yum.repos.d]#seq 10|awk 'i=!i'
1
3
5
7
9
打印奇數(shù),第一行讀進(jìn)來時,i=0,取非就是真,就打印,第二行
讀進(jìn)來時,i是真,取非就是假,假就不打印,第三行讀進(jìn)來時,i是
假,取非就是真,真就打印,這樣只要是奇數(shù)行就是真,就打印
[root@centos6 yum.repos.d]#seq 10|awk '!(i=!i)' ---打印偶數(shù)行
[root@centos6 yum.repos.d]#seq 10|awk '{i=!i;print i}'
1
0
1
0
1
0
1
0
1
0
5、打印從1-10的奇數(shù)和偶數(shù)的方法總結(jié)
方法一:echo打印
[root@centos6 yum.repos.d]#echo {1..10..2}
1 3 5 7 9
[root@centos6 yum.repos.d]#echo {2..10..2}
2 4 6 8 10
方法二:seq
[root@centos6 yum.repos.d]#seq -s " " 1 2 10
[root@centos6 yum.repos.d]#seq -s " " 2 2 10
方法三:sed
[root@centos6 yum.repos.d]#seq 10|sed -n '1~2p'
[root@centos6 yum.repos.d]#seq 10|sed -n '2~2p'
方法四:awk
[root@centos6 yum.repos.d]#seq 10|awk 'i=!i'
[root@centos6 yum.repos.d]#seq 10|awk '!(i=!i)'
6、awk的acction
常用的action分類
(1) Expressions:算術(shù),比較表達(dá)式等
(2) Control statements:if, while等
(3) Compound statements:組合語句
(4) input statements
(5) output statements:print等
7、awk控制語句
- if-else
?語法:if(condition){statement;…}else{ statement}
if(condition1){statement1}else if(condition2){statement2}
else{statement3}
小括號里面是條件判斷,大括號里面是執(zhí)行的動作
?使用場景:對awk取得的整行或某個字段做條件判斷
示例
[root@centos6 yum.repos.d]#awk -F: '{if($3>=1000){print $1,$3}}' /etc/passwd
nfsnobody 65534
[root@centos6 yum.repos.d]#awk -F: '{if($NF=="/bin/bash"){print $1,$3}}' /etc/passwd
root 0
dufu 500
[root@centos6 yum.repos.d]#awk '{if(NF>5){print $0}}' /etc/fstab
[root@centos6 yum.repos.d]#awk -F: '{if($3>=500){printf "commonuser:%-15s\n",$1}else{printf "systemuser: %-15s\n",$1}}' /etc/passwd
systemuser: root
systemuser: bin
systemuser: daemon
systemuser: adm
[root@centos6 yum.repos.d]#awk -F: '{if($3>=500)printf "commonuser:%-15s\n",$1;else printf "systemuser: %-15s\n",$1}' /etc/passwd ---上面也可以用這種寫法
[root@centos6 yum.repos.d]#df |awk -F% '/^\/dev\/sd/{print $1}'|awk '$NF>=80{print $1,$5}'
[root@centos6 yum.repos.d]#awk 'BEGIN{test=100;if(test>90){print "very good"}else if(test>60){print "good"}else{print "no pass"}}'
very good
[root@redhat7 script]#echo {1..10}|awk '{i=1;while(i<=NF){ if($i%2==0){print $i,"oushu"}else {print $i,"jishu"};i++}}'
- while
?while循環(huán)
?語法:while(condition){statement;…}
小括號里面是條件判斷,大括號里面是在這種條件下執(zhí)行的動作
?條件“真”,進(jìn)入循環(huán);條件“假”,退出循環(huán)
?使用場景:
對一行內(nèi)的多個字段逐一類似處理時使用
對數(shù)組中的各元素逐一處理時使用
示例
[root@centos6 yum.repos.d]#awk 'BEGIN{print length("xxxxxxx")}'
7
length(),小括號里面是字符串,可以顯示字符串的長度,注意如果
是字符串一定要加雙引號,如果是變量不加雙引號。
[root@redhat7 rules.d]#awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-693.el7.x86_64 30
root=UUID=1ef020e7-9a49-4a5d-ae32-fb03caef3f29 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=en_US.UTF-8 16
linux16 7
/vmlinuz-0-rescue-fe8e32bbb81547ccb85916d1fe2a32ff 50
root=UUID=1ef020e7-9a49-4a5d-ae32-fb03caef3f29 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
[root@redhat7 rules.d]#awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){if(length($i)>=10){print $i,length($i)};i++}}' /etc/grub2.cfg
/vmlinuz-3.10.0-693.el7.x86_64 30
root=UUID=1ef020e7-9a49-4a5d-ae32-fb03caef3f29 46
crashkernel=auto 16
LANG=en_US.UTF-8 16
/vmlinuz-0-rescue-fe8e32bbb81547ccb85916d1fe2a32ff 50
root=UUID=1ef020e7-9a49-4a5d-ae32-fb03caef3f29 46
crashkernel=auto 16
[root@centos7 ~]#cat f1.txt
1 2 3 4 5 6 7 8 9 10
10 11 12 13 14 15 16 17 18 19 20
[root@centos7 ~]#awk '{i=1;sum=0;while(i<=NF){sum+=i;i++};print sum,i}' f1.txt
55 11
66 12
[root@centos7 ~]#awk '{i=1;sum=0;while(i<=NF){sum+=$i;i++};print sum,i}' f1.txt ---計算每一行的和,因為sum有初始值,所以每一行讀
進(jìn)來的時候sum剛開始都是0,從0開始往上加
55 11
165 12
[root@centos7 ~]#awk '{i=1;while(i<=NF){sum+=$i;i++}}END{print sum}' f1.txt ---END是用于匯總,這里sum沒有初始值,默認(rèn)是0,當(dāng)
第二行讀進(jìn)來的時候,sum的初始值是第一行的和,再整個基礎(chǔ)上繼
續(xù)相加
220
[root@centos7 ~]#awk '{i=1;while(i<=NF){sum+=$i;i++};print sum,i}END{print sum}' f1.txt ---這個可以看的很清楚,當(dāng)sum沒有
在大括號里定義初始值時,第二行讀進(jìn)來時就是在第一行的基礎(chǔ)上相
加。
55 11
220 12
220
- 計算1到100之和的方法總結(jié):
方法一
[root@redhat7 system]#echo {1..100}|tr ' ' '+'|bc
5050
方法二
[root@redhat7 system]#seq -s "+" 100|bc
5050
方法三
[root@redhat7 system]#sum=0;for i in {1..100};do let sum+=i;done;echo $sum
5050
方法四
[root@redhat7 script]#i=1,sum=0;while [ $i -le 100 ];do let sum+=i;let i++;done;echo $sum
方法五
5050
[root@redhat7 script]#for((i=1,sum=0;i<=100;i++));do let sum+=i;done;echo $sum
5050
方法六
[root@redhat7 script]#awk 'BEGIN{sum=0;i=1;while(i<=100){sum+=i;i++};print sum}'
5050
- for循環(huán)
?語法:for(expr1;expr2;expr3) {statement;…}
?常見用法:
for(變量初始化;條件判斷;變量的修正表達(dá)式)
{for-body}
?特殊用法:能夠遍歷數(shù)組中的每一個元素
語法:for(var in array)
示例
[root@redhat7 script]#awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}' /etc/grub2.cfg
- 性能比較
[root@redhat7 script]#time (awk 'BEGIN{for(i=1;i<=100000;i++){sum+=i};print sum}')
5000050000
real 0m0.012s
user 0m0.010s
sys 0m0.002s
[root@redhat7 script]#time (sum=0;for i in {1..100000};do let sum+=i;done;echo $sum)
5000050000
real 0m0.521s
user 0m0.099s
sys 0m0.422s
[root@redhat7 script]#time (seq -s "+" 100000|bc)
5000050000
real 0m0.039s
user 0m0.040s
sys 0m0.003s
可以看出awk的運(yùn)算速度是最快的
- break和continue、next
[root@redhat7 script]#awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i};print sum}'
2500
[root@redhat7 script]#awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}'
2145
[root@redhat7 script]#awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)continue;sum+=i}print sum}'
4984
[root@redhat7 script]#awk -F: '{if($3%2!=0)next;print $1,$3}' /etc/passwd
root 0
daemon 2
lp 4
shutdown 6
mail 8
games 12
ftp 14
systemd-network 192
sshd 74
zhang 1000
apache 48
總結(jié):前兩個和bash里面的用法相同,continue是跳出本輪循,break是跳出整個循環(huán),next是提前結(jié)束對本行處理而直接進(jìn)入下一行處理(awk自帶行的循環(huán))。
8、awk數(shù)組
awk的數(shù)組為關(guān)聯(lián)數(shù)組,即索引下標(biāo)為任意的字符串,不是數(shù)字表示索引。若要遍歷數(shù)組中的每個元素,要使用for循環(huán) for(var in array)
注意:var會遍歷數(shù)組array的每個索引。
示例
[root@redhat7 app]#awk -F: '{line[$7]++}END{for(i in line){print i,line[i]}}' /etc/passwd
/bin/sync 1
/bin/bash 3
/sbin/nologin 16
/sbin/halt 1
/sbin/shutdown 1
表示第七列的值為數(shù)組line的索引下標(biāo),如果第七列的值有相同的,
數(shù)組line的值就加1,i會遍歷數(shù)組line的每一個索引值,打印i就表示第
七列的值,line這個數(shù)組,因為沒有賦值,所以剛開始的時候是0,當(dāng)
有相同索引下標(biāo)時,就加1,這樣不斷累加,line[i]就可以表示出重復(fù)
的索引值出現(xiàn)了多少次,重復(fù)一次,數(shù)組line就加1。
[root@redhat7 app]#netstat -nat|awk '/^tcp/{state[$NF]++}END{for(i in state){print i,state[i]}} '
LISTEN 5
ESTABLISHED 2
[root@redhat7 app]#cat f1
aaaaa
ddddd
ccccc
aaaaa
bbbbb
ccccc
ddddd
bbbbb
[root@redhat7 app]#awk '!line[$0]++' f1
aaaaa
ddddd
ccccc
bbbbb
這種用法可以用于去掉重復(fù)的行,并且原來的次序不會打亂,比用sort和uniq好。
解釋說明:因為line這個數(shù)組沒有賦值,所以剛開始的時候line這
個數(shù)組的值為0,把文件的每一行做為數(shù)組的索引值,如果沒有遇到
相同的行時,line的數(shù)組值都是0,然后先取反,取反后為真,就打印
整行,然后加1,此時數(shù)組的值為1,這里省略了action,就會默認(rèn)打
印整行,當(dāng)有相同的行讀進(jìn)來時。line數(shù)組的值為1,取反就為假。不
打印,line數(shù)組的值加1,變?yōu)?,當(dāng)有第三個相同的行時,因為line的
值不是0,所以每次取反,都為假,不會執(zhí)行打印,利用這種方法就
可以去掉重復(fù)的行了。
注意:!的優(yōu)先級要比++的優(yōu)先級高,先進(jìn)行非判斷是否打印,然后再++
[root@redhat7 app]#netstat -nt|awk -F "[[:space:]:]+" '/^tcp/{ip[$6]++}END{for(i in ip){print i,ip[i]}}'|sort -k2 -nr|head -n 10
-F "[[:space:]:]+" 表示以空格或者冒號做為分割符,這樣可以用一次awk取出ip地址那行
9、awk函數(shù)
?數(shù)值處理:
rand():返回0和1之間一個隨機(jī)數(shù)
[root@redhat7 app]#awk 'BEGIN{print rand()}'
0.237788
[root@redhat7 app]#awk 'BEGIN{print rand()}'
0.237788
[root@redhat7 app]#awk 'BEGIN{print rand()}'
0.237788
[root@redhat7 app]#awk 'BEGIN{srand();print rand()}'
0.0522516 ---必須和srand()配合使用,才能顯示0-1之前的隨機(jī)
數(shù),否則值不會改變,就像上面的一樣,值不是隨機(jī)數(shù)
[root@redhat7 app]#awk 'BEGIN{srand();print rand()*100}'
26.8591 ---乘以100后不是整數(shù)
[root@redhat7 app]#awk 'BEGIN{srand();print int(rand()*100)}'
[root@redhat7 app]#awk 'BEGIN{srand();for (i=1;i<=10;i++){print int(rand()*100)}}' --可以打印10個隨機(jī)數(shù)
22 ---可以用init聲明是整數(shù)
?字符串處理:
?length([s]):返回指定字符串的長度,小括號里面如果是字符串,要用雙引號,如果是變量就不用了
?sub(r,s,[t]):對t字符串進(jìn)行搜索,r表示模式匹配的內(nèi)容,并將第一個匹配的內(nèi)容替換為s
[root@redhat7 app]#echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$1)' ---因沒有指定分割符,所以默認(rèn)是空格做為分隔符,搜索第一列,將冒號替換為-號
2008-08:08 08:08:08
?gsub(r,s,[t]):對t字符串進(jìn)行搜索,r表示模式匹配的內(nèi)容,并全部替換為s所表示的內(nèi)容
[root@redhat7 app]#echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$0)'
2008-08-08 08-08-08
?split(s,array,[r]):以r為分隔符,切割字符串s,并將切割后的結(jié)果保存至array所表示的數(shù)組中,第一個索引值為1,第二個索引值為2,…
[root@redhat7 app]#netstat -nt|awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'
解釋:因為沒有指定輸入分割符,所以默認(rèn)是空白字符,模式匹配,
匹配以tcp打頭的行,以冒號做為分割符,切割第五列,將切割的結(jié)
果保存在ip這個數(shù)組中,并且切割的第一列的值保存在ip[1]這個索引
為1的數(shù)組元素中,然后將這個數(shù)組元素定義為count數(shù)組的索引值,
就可以利用這種方式去顯示每個ip地址出現(xiàn)的次數(shù)。
計算出男生和女生的總分?jǐn)?shù)和平級成績
[root@redhat7 app]#cat f1
mage 100 male
wang 90 male
zhang 80 female
li 100 female
[root@redhat7 app]#awk '{total[$3]+=$2;num[$3]++}END{for(name in total){print name,total[name],total[name]/num[name]}}' f1
[root@redhat7 app]#awk '{if($3 == "male"){msum+=$2;mnum++}else{fsum+=$2;fnum++}}END{printf "msum=%d mavg=%.2f\nfsum=%d favg=%.2f\n",msum,msum/mnum,fsum,fsum/fnum}' f1
- 自定義函數(shù)
格式:
function name ( parameter, parameter, ... ) {
statements
return expression
}
示例:
#cat fun.awk
function max(v1,v2) {
v1>v2?var=v1:var=v2
return var
}
BEGIN{a=3;b=2;print max(a,b)}
#awk –f fun.awk
10、awk腳本
awk中調(diào)用shell命令
?system命令
?空格是awk中的字符串連接符,如果system中需要使用awk中的變量可以使用空格分隔,或者說除了awk的變量外其他一律用""引用起來。
awk BEGIN'{system("hostname") }'
awk'BEGIN{score=100; system("echo your score is " score) }'
如何在ssh日志文件中找到外部主機(jī)ssh連接失敗的ip地址的數(shù)目,如果連接失敗的次數(shù)大于5次,就放到防火墻里禁止用ssh連接本主機(jī)。
方法一
[root@centos6 app]#vim awk.sh
1 #!/bin/bash
2 #
3 while true;do
4 cat /var/log/secure|awk '/Failed/{ip[$(NF-3)]++}END{for(i in ip){if(ip[i]>=5){system("iptables -A INPUT -s "i" -j REJECT")}}}'
5 sleep 5
6 done
方法二
[root@centos6 app]#cat jianchassh.sh
#!/bin/bash
#
while true;do
cat /var/log/secure |grep "Failed"|awk '{ip[$(NF-3)]++}END{for(i in ip){print i,ip[i]}}'> /app/f6
cat /app/f6 |while read file;do
ip=`echo $file|cut -d ' ' -f1`
num=`echo $file|cut -d ' ' -f2`
if [ $num -ge 5 ];then
iptables -A INPUT -s $ip -j REJECT
fi
done
sleep 2m
done
awk腳本
#cat f1.awk
{if($3>=1000)print $1,$3}
#awk -F: -f f1.awk /etc/passwd
#cat f2.awk
#!/bin/awk–f --要寫awk的蛇棒機(jī)制
#this is a awkscript
{if($3>=1000)print $1,$3}
#chmod+x f2.awk
#f2.awk –F: /etc/passwd
向awk腳本傳遞參數(shù)
#cat test.awk
#!/bin/awk –f
{if($3 >=min && $3<=max)print $1,$3}
#chmod +x test.awk
#test.awk -F: min=100 max=200 /etc/passwd