00x01 awk介紹
awk: Aho, Weinberger, Kernighan,報告生成器,格式化文本輸出,用於在linux/unix下對文本和數據進行處理。數據可以來自標準輸入、一個或多個文件,或其它命令的輸出。它支持用戶自定義函數和動態正則表達式等先進功能
有多種版本: New awk(nawk), GNU awk(gawk)
gawk:模式掃描和處理語言
00x02 awk基本用法
基本用法:
awk [options] ‘program’ var=value file…
awk [options] -f programfile var=value file…
awk [options] 'BEGIN{ action;… } pattern{ action;… } END{action;… }' file ...
awk 程序通常由: BEGIN語句塊、能夠使用模式匹配的通用語句塊、 END語句塊,共3部分組成
program通常是被單引號或雙引號中
選項:
-F 指明輸入時用到的字段分隔符
-v var=value: 自定義變量
基本格式:
awk [options] 'program' file…
program:pattern{action statements;..}
pattern和action:
pattern部分決定動作語句何時觸發及觸發事件
BEGIN,END
action statements對數據進行處理,放在{}內指明
print, printf
分割符、域和記錄
awk執行時, 由分隔符分隔的字段(域)標記$1,$2..$n稱爲域標識。 $0爲所有域,注意:和shell中變量$符含義不同
文件的每一行稱爲記錄
省略action,則默認執行 print $0 的操作
00x03 awk工作原理
第一步:執行BEGIN{action;… }語句塊中的語句
第二步:從文件或標準輸入(stdin)讀取一行,然後執行pattern{action;… }語句塊,它逐行掃描文件,從第一行到最後一行重複這個過程,直到文件全部被讀取完畢。
第三步:當讀至輸入流末尾時,執行END{action;…}語句塊
BEGIN語句塊在awk開始從輸入流中讀取行之前被執行,這是一個可選的語句塊,比如變量初始化、打印輸出表格的表頭等語句通常可以寫在BEGIN語句塊中
END語句塊在awk從輸入流中讀取完所有的行之後即被執行,比如打印所有行的分析結果這類信息彙總都是在END語句塊中完成,它也是一個可選語句塊
pattern語句塊中的通用命令是最重要的部分,也是可選的。如果沒有提供pattern語句塊,則默認執行{ print },即打印每一個讀取到的行, awk讀取的每一行都會執行該語句塊
00x04 print
print格式: print item1, item2, ...
要點:
(1) 逗號分隔符
(2) 輸出的各item可以字符串,也可以是數值;當前記錄的字段、
變量或awk的表達式
(3) 如省略item,相當於print $0
示例:
awk '{print "hello,awk"}'
awk –F: '{print}' /etc/passwd
awk –F: ‘{print “wang”}’ /etc/passwd
awk –F: ‘{print $1}’ /etc/passwd
awk –F: ‘{print $0}’ /etc/passwd
awk –F: ‘{print $1”\t”$3}’ /etc/passwd
tail –3 /etc/fstab |awk ‘{print $2,$4}’
00x05 變量
變量:常用內置變量
a、FS
FS field-separator 輸入字段分隔符,默認爲空白字符
使用FS的好處就是可以在內部調用這個變量
[root@localhost tmp]# awk -v FS=":" '{print $1,FS,$3}' passwd root : 0 bin : 1 daemon : 2 adm : 3 lp : 4 sync : 5
[root@localhost tmp]# awk -F ":" '{print $1":"$3}' passwd root:0 bin:1 daemon:2 adm:3 lp:4 sync:5
b、OFS
output field-separator 輸出字段分隔符,默認爲空白字符
[root@localhost tmp]# awk -v FS=":" -v OFS="$" '{print $1,$3,$7}' passwd root$0$/bin/bash bin$1$/sbin/nologin daemon$2$/sbin/nologin adm$3$/sbin/nologin
c、RS
輸入記錄分隔符,指定輸入時的換行符,原換行符仍有效
[root@localhost tmp]# awk -v FS=":" -v OFS="$" '{print $1,$3,$7}' passwd nobody:x:99:99:Nobody:/:/sbin/nologin systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin systemd-network:x:192:192:systemd Network
[root@localhost tmp]# cat test list a b dd list2 a2 b2 dd2 list4 a3 b3 dd3 [root@localhost tmp]# cat test |awk -v RS=" " -v OFS="++" '{print $1,$2}' list++ a++ b++ dd++list2 #指定 RS“ ”,dd\nlist2,FS默認爲空白字符,$1就是dd a2++ b2++ dd2++list4 a3++ b3++ dd3++
d、 ORS
輸出記錄分隔符,輸出時用指定符號代替換行符
[root@localhost tmp]# awk -v RS=" " -v ORS="%" '{print}' passwd root:x:0:0:yemo,62985600:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin systemd-bus-proxy:x:999:997:systemd%Bus%Proxy:/:/sbin/nologin systemd-network:x:192:192:systemd%Network%Management:/:/sbin/nologin dbus:x:81:81:System%message%bus:/:/sbin/nologin polkitd:x:998:996:User%for%polkitd:/:/sbin/nologin tss:x:59:59:Account%used%by%the%trousers%package%to%sandbox%the%tcsd%daemon:/dev/null:/sbin/nologin
e、 NF
字段數量
[root@localhost tmp]# cat passwd |awk -F: '{print NF}' #不需要使用$ 7 7 7 7
可以用於循環每行每個字段
[root@localhost tmp]# cat passwd |awk -F: '{for(i=0;i<NF;i++){print $i}}' root:x:0:0:yemo,62985600:/root:/bin/bash root x 0 0 yemo,62985600 /root bin:x:1:1:bin:/bin:/sbin/nologin
f、 NR
行號
[root@localhost tmp]# cat passwd |awk -F: '{print NR}' 1 2 3 4 [root@localhost tmp]# awk 'END{print NR}' passwd 22
e、 FNR
各文件分別計數,行號
[root@localhost tmp]# awk '{print FNR}' /etc/fstab /etc/inittab 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1 2 ...
f、 FILENAME
當前文件名
[root@localhost tmp]# awk '{print FILENAME}' /etc/fstab /etc/fstab /etc/fstab /etc/fstab /etc/fstab /etc/fstab /etc/fstab
g、 ARGC
命令行參數的個數
[root@localhost tmp]# awk 'END{print ARGC}' /etc/fstab /etc/inittab 3
h、 ARGV
數組,保存的是命令行所給定的各參數
[root@localhost tmp]# awk 'END{print ARGV[1]}' /etc/fstab /etc/inittab /etc/fstab [root@localhost tmp]# awk 'END{print ARGV[0]}' /etc/fstab /etc/inittab awk [root@localhost tmp]# awk 'END{print ARGV[2]}' /etc/fstab /etc/inittab /etc/inittab
00x06 自定義變量和環境變量
自定義變量(區分字符大小寫)
(1) -v var=value
(2) 在program中直接定義
[root@localhost tmp]# awk -v a="sh" 'BEGIN{print a}' sh
[root@localhost tmp]# cat awkscript {print script,$1,$2} [root@localhost tmp]# awk -F: -f awkscript script="awk" /etc/passwd awk root x #引用文件的變量,相當於已經定義,不用再-v聲明 awk bin x awk daemon x awk adm x awk lp x awk sync x awk shutdown x awk halt x
環境變量:
00x07 printf格式化輸出
a、格式printf “FORMAT” , item1, item2, ...
(1) 必須指定FORMAT
(2) 不會自動換行,需要顯式給出換行控制符, \n
(3) FORMAT中需要分別爲後面每個item指定格式符
b、實例
printf '\n'$(tput setaf 2; tput setab 0; tput bold)'background color show'$(tput sgr0)'\n\n'
%s字符串,\t打印tab,\n回車,printf默認不會輸出換行符
[root@localhost matrix]# echo "hello world"|awk '{printf "%s\t%s\n",$1,$2}' hello world
%d十進制
[root@localhost matrix]# echo "12580 124"|awk '{printf "%d\t%d\n",$1,$2}' 12580 124
%o無符號八進制
[root@localhost matrix]# echo "12580 124"|awk '{printf "%o\t%o\n",$1,$2}' 30444 174
%x十六進制
[root@localhost matrix]# echo "12580 124"|awk '{printf "%x\t%x\n",$1,$2}' 3124 7c
[root@localhost matrix]# awk -F: '{printf "Username: %s,UID:%d\n",$1,$3}' /tmp/passwd Username: root,UID:0 Username: bin,UID:1 Username: daemon,UID:2 Username: adm,UID:3 Username: lp,UID:4
00x08 操作符
算術操作符:
x+y, x-y, x*y, x/y, x^y, x%y
-x: 轉換爲負數
+x: 轉換爲數值
[root@localhost matrix]# awk 'BEGIN{print 2-4}' -2 [root@localhost matrix]# awk 'BEGIN{print 2^3}' 8 [root@localhost matrix]# awk -v a=m 'BEGIN{print +a}' 0 [root@localhost matrix]# awk -v a=m 'BEGIN{print a}' m [root@localhost matrix]# awk -v a=5 'BEGIN{print -a}' -5
字符串拼接
[root@localhost matrix]# awk -v a="hello" -v b="Rie Kugimiya" 'BEGIN{print ab}' [root@localhost matrix]# awk -v a="hello" -v b="Rie Kugimiya" 'BEGIN{print a b}' helloRie Kugimiya
賦值操作符: =, +=, -=, *=, /=, %=, ^=,++, --
[root@localhost matrix]# awk 'BEGIN{b=10;print b}' 10 [root@localhost matrix]# awk -F: '{for(i=0;i<NF;i++){print i}}' /tmp/passwd 0 1 2 3 4 5 6 0 1 2 3 4 5 6
比較操作 ==, !=, >, >=, <, <=
[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($3>100){print $0}}' systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin polkitd:x:998:996:User for polkitd:/:/sbin/nologin abrt:x:173:173::/etc/abrt:/sbin/nologin yemo:x:1000:1000::/home/yemo:/bin/bash
模式匹配 ~:左邊是否和右邊匹配包含
[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($1 ~/.*oo.*/){print}}' root:x:0:0:yemo,62985600:/root:/bin/bash [root@localhost matrix]# cat /etc/passwd|awk -F: '{if($0 ~/.*oo.*/){print}}' root:x:0:0:yemo,62985600:/root:/bin/bash lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin mail:x:8:12:mail:/var/spool/mail:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin
!~:是否不匹配
[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($0 !~/.*oo.*/){print}}' bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin dbus:x:81:81:System message bus:/:/sbin/nologin
邏輯操作符 與&&,或||,非!
[root@localhost matrix]# cat /etc/passwd|awk -F: '{if($0 !~/.*oo.*/ &&$3 >100 ){print}}' systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin polkitd:x:998:996:User for polkitd:/:/sbin/nologin abrt:x:173:173::/etc/abrt:/sbin/nologin yemo:x:1000:1000::/home/yemo:/bin/bash [root@localhost matrix]# awk -F: '!($3>=500) {print $3}' /etc/passwd 0 1 2 3 4 5 6
函數調用
自定義函數調用
[root@localhost matrix]# echo "11 22"|awk '{print "max=",max($1,$2)}function max(a,b){if(a>b){return a;}else{return b;}}' max= 22
內部函數調用
[root@localhost matrix]# echo "ad 12 22 dd"|awk 'split($0,a){for(i in a)printf a[i]}' ddad1222
條件表達式
三元表達式: selector?if-true-expression:if-false-expression
[root@localhost matrix]# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd root:Sysadmin or SysUser bin:Sysadmin or SysUser daemon:Sysadmin or SysUser adm:Sysadmin or SysUser lp:Sysadmin or SysUser sync:Sysadmin or SysUser shutdown:Sysadmin or SysUser halt:Sysadmin or SysUser mail:Sysadmin or SysUser operator:Sysadmin or SysUser games:Sysadmin or SysUser ftp:Sysadmin or SysUser nobody:Sysadmin or SysUser systemd-bus-proxy:Sysadmin or SysUser systemd-network:Sysadmin or SysUser dbus:Sysadmin or SysUser polkitd:Sysadmin or SysUser tss:Sysadmin or SysUser abrt:Sysadmin or SysUser postfix:Sysadmin or SysUser sshd:Sysadmin or SysUser yemo:Common User
[root@localhost matrix]# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%-15s:%-s\n",$1,usertype}' /etc/passwd root :Sysadmin or SysUser bin :Sysadmin or SysUser daemon :Sysadmin or SysUser adm :Sysadmin or SysUser lp :Sysadmin or SysUser sync :Sysadmin or SysUser shutdown :Sysadmin or SysUser halt :Sysadmin or SysUser mail :Sysadmin or SysUser
00x09 PATTERN:根據pattern條件,過濾匹配的行,再做處理
(1)如果未指定:空模式,匹配每一行
[root@localhost tmp]# awk '{print $1}' test list list2 list4
(2) /regular expression/:僅處理能夠模式匹配到的行,需要用/ /括起來
[root@localhost tmp]# cat passwd |awk -F: '/^root\>/ {print }' root:x:0:0:yemo,62985600:/root:/bin/bash #支持位置鉚釘和單詞鉚釘 [root@localhost tmp]# cat passwd |awk -F: '/root/ {print }' #包含root的全都匹配 root:x:0:0:yemo,62985600:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin
(3) relational expression: 關係表達式,結果爲“真”纔會被處理
真:結果爲非0值,非空字符串
假:結果爲空字符串或0值
[root@localhost tmp]# cat passwd |awk -F: 'i=1;j=1{print i,j}' #i=1後默認有{print $0} root:x:0:0:yemo,62985600:/root:/bin/bash 1 1 bin:x:1:1:bin:/bin:/sbin/nologin 1 1 daemon:x:2:2:daemon:/sbin:/sbin/nologin 1 1
[root@localhost tmp]# cat passwd |awk -F: '$3>500 {print }' systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin polkitd:x:998:996:User for polkitd:/:/sbin/nologin yemo:x:1000:1000::/home/yemo:/bin/bash
匹配finger空的行
[root@localhost tmp]# cat passwd |awk -F: '!$5 {print }' abrt:x:173:173::/etc/abrt:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin yemo:x:1000:1000::/home/yemo:/bin/bash
匹配默認bash是/bin/bash的用戶
[root@localhost tmp]# awk -F: '$NF=="/bin/bash"{print $1,$NF}' passwd root /bin/bash yemo /bin/bash
匹配 bash結尾
[root@localhost tmp]# awk -F: '$NF ~/bash$/{print $1,$NF}' passwd root /bin/bash yemo /bin/bash
(4) line ranges: 行範圍
startline,endline: /pat1/,/pat2/ 不支持直接給出數字格式
[root@localhost tmp]# awk -F: '/^root\>/,/^mail\>/{print $1,$3}' passwd root 0 #類似sed的用法 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8
[root@localhost tmp]# awk -F: '(NR>=3&&NR<=10){print $1,$3}' passwd daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 operator 11
(5) BEGIN/END模式
BEGIN{}: 僅在開始處理文件中的文本之前執行一次
END{}:僅在文本處理完成之後執行一次
[root@localhost tmp]# seq 10|awk '' [root@localhost tmp]# seq 10|awk '1' 1 2 3 4 5 6 7 8 9 10 [root@localhost tmp]# seq 10|awk '{i=!i;print i}' 1 0 1 0 1 0 1 0 1 0 [root@localhost tmp]# seq 10|awk '{i=!i}' [root@localhost tmp]# seq 10|awk 'i=0;i=!i' 1 2 3 4 5 6 7 8 9 10 [root@localhost tmp]# seq 10|awk 'i=1;i=!i' 1 2 3 4 5 6 7 8 9 10 [root@localhost tmp]# seq 10|awk -v i=1 'i=!i' 2 4 6 8 10 [root@localhost tmp]# seq 10|awk '!(i=!i)' 2 4 6 8 10
00x0a action
00x0b 控制語句
1)if循環
if(condition){statement;…}[else statement]
[root@localhost tmp]# cat passwd |awk -F: '{if($3>500){print}}' systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin polkitd:x:998:996:User for polkitd:/:/sbin/nologin yemo:x:1000:1000::/home/yemo:/bin/bash
[root@localhost tmp]# cat passwd |awk -F: '{if($NF=="/bin/bash"){print}}' root:x:0:0:yemo,62985600:/root:/bin/bash yemo:x:1000:1000::/home/yemo:/bin/bash
[root@localhost tmp]# cat passwd |awk -F: '{if($5!=""){print}}' root:x:0:0:yemo,62985600:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@localhost tmp]# cat passwd |awk -F: '{if($3>500){printf "commusr:%s\n",$1}else{printf "sysuser:%s\n",$1 }}' sysuser:root sysuser:bin sysuser:daemon sysuser:adm sysuser:games sysuser:ftp sysuser:nobody commusr:systemd-bus-proxy sysuser:systemd-network sysuser:dbus commusr:polkitd sysuser:tss sysuser:abrt sysuser:postfix sysuser:sshd commusr:yemo
[root@localhost tmp]# df -P|awk -F "% " '/dev\/sd/ {print}'|awk '{if($5>3)printf "%s\t%s\n",$1,$5}' /dev/sda2 4% /dev/sda1 3%
if(condition1){statement1}else if(condition2){statement2}else{statement3}
[root@localhost tmp]# echo "10 99 100 60 50"|awk '{for(i=1;i<(NF+1);i++) {if($i>=90){print $i,"verygood";}else if($i>=60&&$i<90){print $i,"is ok";}else {print $i"you are too low"} }}' 10you are too low 99 verygood 100 verygood 60 is ok 50you are too low
while循環
語法: while(condition){statement;…}
條件“真”,進入循環;條件“假”, 退出循環
使用場景:
對一行內的多個字段逐一類似處理時使用
對數組中的各元素逐一處理時使用
[root@localhost tmp]# awk '/^\s*linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.0-514.el7.x86_64 30 root=UUID=cb8a4d4d-51c6-417f-a8d8-fc8948450fcd 46 ro 2 crashkernel=auto 16 rhgb 4 quiet 5 LANG=en_US.UTF-8 16 net.ifnames=0 13
[root@localhost tmp]# awk '/^\s*linux16/{i=1;while(i<=NF){if(length($i)>10){print $i,length($i)};i++ } }' /etc/grub2.cfg /vmlinuz-3.10.0-514.el7.x86_64 30 root=UUID=cb8a4d4d-51c6-417f-a8d8-fc8948450fcd 46 crashkernel=auto 16 LANG=en_US.UTF-8 16 net.ifnames=0 13 /vmlinuz-0-rescue-8665dcc4833c41eaa11fa716f7dcd792 50 root=UUID=cb8a4d4d-51c6-417f-a8d8-fc8948450fcd 46 crashkernel=auto 16
do-while循環
語法: do {statement;…}while(condition)
意義:無論真假,至少執行一次循環體
[root@localhost tmp]# awk 'BEGIN{total=0;i=0;do{total+=i;i++;}while(i<=100);print total}' 5050 [root@localhost tmp]# awk 'BEGIN{total=1;i=1;do{total+=i;i++;}while(i<=0);print total}' 2
[root@localhost tmp]# awk 'BEGIN{i=0;print ++i,i}' #先加後賦值 1 1 [root@localhost tmp]# awk 'BEGIN{i=0;print i++,i}' #先賦值在加 0 1
for循環
語法:for(expr1;expr2;expr3) {statement;…}
常見用法:
for(variable assignment;condition;iteration process){for-body}
特殊用法:能夠遍歷數組中的元素
echo "10 99 100 60 50"|awk '{for(i=1;i<(NF+1);i++) {if($i>=90){print $i,"verygood";}else if($i>=60&&$i<90){print $i,"is ok";}else {print $i"you are too low"} }}' 10you are too low 99 verygood 100 verygood 60 is ok 50you are too low
[root@localhost tmp]# cat access.log |awk '{++arr[$1]}{for(i in arr){print i,arr[i]}}' 192.168.1.44 34 172.16.100.76 204 192.168.1.100 12 192.168.1.101 1 192.168.1.110 83 192.168.99.72 18 172.16.100.125 18 127.0.0.1 7 192.168.1.121 13 192.168.1.112 27 172.16.0.100 4 172.16.100.126 3 192.168.1.113 583 172.16.23.100 14 192.168.1.114 12 192.168.6.1 42 172.16.250.227 68 192.168.1.106 22 172.16.233.133 112 192.168.1.107 68 192.168.1.108 3
switch語句
語法: switch(expression) {case VALUE1 or /REGEXP/:statement1; case VALUE2 or /REGEXP2/: statement2;...; default: statementn}
break和continue
[root@localhost ~]# awk 'BEGIN{sum=0;for(i=0;i<=100;i++){if(i%2==0)continue;sum+=i}print sum }' 2500
[root@localhost ~]# awk 'BEGIN{sum=0;for(i=0;i<=100;i++){if(i==55)break;sum+=i}print sum }' 1485
[root@localhost ~]# awk -F: '{if($3%2!=0)next;print $1,$3}' /tmp/passwd root 0 daemon 2 lp 4 shutdown 6 mail 8 games 12 ftp 14 systemd-network 192 polkitd 998 sshd 74 yemo 1000
00x0b awk數組
a) 關聯數組: array[index-expression]
index-expression:
(1) 可使用任意字符串;字符串要使用雙引號括起來
(2) 如果某數組元素事先不存在,在引用時, awk會自動創建此元素,並將其值初始化爲“空串”
若要判斷數組中是否存在某元素,要使用“index in array”格式進行遍歷
若要遍歷數組中的每個元素,要使用for循環
for(var in array) {for-body}
注意: var會遍歷array的每個索引
[root@localhost tmp]# cat access.log |awk '{++arr[$1]}{for(i in arr){print i,arr[i]}}' 192.168.1.44 34 172.16.100.76 204 192.168.1.100 12 192.168.1.101 1 192.168.1.110 83 192.168.99.72 18 172.16.100.125 18 127.0.0.1 7 192.168.1.121 13 192.168.1.112 27 172.16.0.100 4 172.16.100.126 3 192.168.1.113 583 172.16.23.100 14 192.168.1.114 12 192.168.6.1 42 172.16.250.227 68 192.168.1.106 22 172.16.233.133 112 192.168.1.107 68 192.168.1.108 3
使用關聯數組對重複IP地址計數,以IP地址爲索引,出現相同索引的就自加,達到計數的目的,數組缺省值爲0。
00x0c 函數
a)內置函數
01 sub函數匹配記錄中最大、最靠左邊的子字符串的正則表達式,並用替換字符串替換這些字符串。如果沒有指定目標字符串就默認使用整個記錄。替換隻發生在第一次匹配的時候。
sub (regular expression, substitution string):
sub (regular expression, substitution string, target string)
[root@localhost tmp]# awk '{sub(/a/,"test");print}' test listtest a ba dad listtest2 a2 ba2 dad2 listtest4 a3 ba3 dad3 [root@localhost tmp]# cat test lista a ba dad lista2 a2 ba2 dad2 lista4 a3 ba3 dad3
02 gsub函數作用如sub,但它在整個文檔中進行匹配。
[root@localhost tmp]# awk '{gsub(/a/,"test");print}' test listtest test btest dtestd listtest2 test2 btest2 dtestd2 listtest4 test3 btest3 dtestd3
03 index 函數返回子字符串第一次被匹配的位置,偏移量從位置1開始。
index(string, substring)
04 substr函數返回從位置1開始的子字符串,如果指定長度超過實際長度,就返回整個字符串。
substr( string, starting position )
substr( string, starting position, length of string )
05 split函數可按給定的分隔符把字符串分割爲一個數組。如果分隔符沒提供,則按當前FS值進行分割。
split( string, array, field separator )
split( string, array )
06 length函數返回記錄的字符數。
length( string )
length
07 match函數返回在字符串中正則表達式位置的索引,如果找不到指定的正則表達式則返回0。match函數會設置內建變量RSTART爲字符串中子字符串的開始位置,RLENGTH爲到子字符串末尾的字符個數。substr可利於這些變量來截取字符串。
match( string, regular expression )
08 toupper和tolower函數可用於字符串大小間的轉換,該功能只在gawk中有效。
toupper( string )
tolower( string )
b) 數學函數
00x0d 通過system調用系統命令
空格是awk中的字符串連接符,如果system中需要使用awk中的變量可以使用空格分隔,或者說除了awk的變量外其他一律用""引用起來。
[root@localhost ~]# awk 'BEGIN{system("hostname")}' localhost.localdomain [root@localhost ~]# awk 'BEGIN{s=100;system("echo your score is" s)}' your score is100 [root@localhost ~]# awk 'BEGIN{s=100;system("echo your score is " s)}' your score is 100
00x0e 創建awk腳本
[root@localhost tmp]# vim tstawk.awk [root@localhost tmp]# cat tstawk.awk #!/bin/awk -f {if($3>=1000)print $1,$3} [root@localhost tmp]# awk -F: -f tstawk.awk passwd yemo 1000
[root@localhost tmp]# chmod +x tst2.awk [root@localhost tmp]# cat tst2.awk #!/bin/awk -f {if($3>=1000)print $1,$3} [root@localhost tmp]# ./tst2.awk -F: passwd yemo 1000
向awk腳本傳遞參數
格式:
awkfile var=value var2=value2... Inputfile
注意:在BEGIN過程中不可用。直到首行輸入完成以後,變量纔可用。可以通過-v 參數,讓awk在執行BEGIN之前得到變量的值。命令行中每一個指定的變量都需要一個-v參數
[root@localhost tmp]# cat tst2.awk #!/bin/awk -f {if($3>=min && $3<=max)print $1,$3} [root@localhost tmp]# ./tst2.awk -F: min=100 max=500 passwd systemd-network 192 abrt 173
實例:
對fstab文件取單詞並計數排序
[root@localhost tmp]# cat /etc/fstab |tr "[:punct:]" " " |awk '{split($0,arr," ");for(i in arr){brr[arr[i]]++ }} END{for(k in brr){print brr[k],k}} '|sort -nr 6 UUID 6 defaults 5 xfs 3 8 2 swap 2 fstab 2 by 1 Wed 1 var 1 under 1 See 1 reference 1 pages
提取字符串中數字
[root@localhost tmp]# echo "Yd$C@M05MB%9&Bdh7dq+YVixp3vpw"|awk -F "[^[:digit:]]" '{for(i=1;i<=NF;i++){printf "%s",$i}}' 05973
[root@localhost tmp]# ss -ntl|awk -F "[ :]" '/^[^S]/ {arr[$6]++}END{for(i in arr){print arr[$i],i}}'|sort -nr
去掉一個最高一個最低求平均值
馮泉 100 100 96 95 100 96 100 97 萬永振 100 95 90 88 95 98 95 98 徐亮偉 100 100 90 98 90 98 100 96 曹雅楠 100 100 95 90 97 90 95 98 陳派宇 90 95 95 96 100 98 100 96 李峯 90 90 90 85 92 95 95 98 餘連輝 90 93 95 92 95 95 96 95 侯亞光 90 96 97 90 90 85 95 90 王續 85 92 98 98 90 95 蔚雷 92 92 96 90 90 80 蘇浩智 88 96 85 95 90 90 徐登輝 85 95 88 90 90 90 林章益 91 97 98 90 100 90 黃品清 85 97 88 90 90 90 李健 85 95 90 88 80 80 宮全樂 88 95 90 88 90 100 萬良 89 95 95 88 100 100 馬自強 88 97 90 88 90 90 任冠亞 88 97 98 90 100 100
解法1
[root@localhost tmp]# cat awk_tst.tst |awk '{for(i=2;i<=NF;i++){a[i]=$i};sum=0;tmp=0;for(j in a){for(k in a){if(a[k]>a[j]){tmp=a[k];a[k]=a[j];a[j]=tmp;}}}for(s=2;s<length(a);s++){sum+=a[s]};arr=sum/(length(a)-2);print $1,arr;delete a}'