awk命令详解

我与影子孤独终老i 提交于 2020-01-12 20:16:45

awk 工作原理和基本用法说明

常见选项:
-F “分隔符” 指明输入时用到的字段分隔符
-v var=value 变量赋值
动作:printf
说明:
逗号分隔符
输出item可以字符串,也可是数值;当前记录的字段、变量或awk的表达式
如省略item,相当于print $0
范例:

[root@I|158|~]#awk -F: '{print $1,$3}' /etc/passwd
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
operator 11
games 12
ftp 14g
nobody 99
[root@I|160|~]#awk -F: '{print $1"\t"$3}' /etc/passwd
root	0
bin	1
daemon	2
adm	3
lp	4
sync	5
shutdown	6
halt	7
mail	8
operator	11
games	12
ftp	14
[root@I|162|~]#grep "^UUID" /etc/fstab 
UUID=7e896ac6-4ee4-4533-ad7e-578c71560735 /                       xfs     defaults        0 0
UUID=a063884c-6421-4581-841b-a13cdc73c254 /boot                   xfs     defaults        0 0
UUID=da6657db-cf66-4ef8-b39f-ff6cf39414f6 /data                   xfs     defaults        0 0
UUID=09bcc722-93e2-497c-a51b-480bc92fafc5 swap                    swap    defaults        0 0
UUID=ed7ec688-ffc1-401f-9af9-ab6224d0aab1 /mnt			ext4     defaults       0 0
UUID=17a95356-e38c-434a-94fc-99819021cc87 swap 			swap  	defaults	0 0
[root@I|161|~]#grep "^UUID" /etc/fstab | awk {'print $2,$3'}
/ xfs
/boot xfs
/data xfs
swap swap
/mnt ext4
swap swap
[root@I|166|~]#df | awk -F"[[:space:]]+|%" '{print $5}'
已用
0
0
2
0
7
1
1
18
1
1
100
[root@I|168|~]#df | awk -F"[[:space:]]+|%" '/^\/dev\/sd{print $5}'
7
1
1
18

awk变量
awk中的变量分为:内置和自定义变量

常见的内置变量

FS:输入字段分隔符,默认为空白字符,功能相当于 -F
范例:

awk -v FS=":" '{print $1FS$3}' /etc/passwd
awk –F:   '{print $1,$3,$7}'   /etc/passwd 
S=:;awk -v FS=$S '{print $1FS$3}' /etc/passwd

OFS:输出字段分隔符,默认为空白字符

[root@centos8|2|~]#awk -v FS=':' -v OFS=':' '{print $1,$3,$7}' /etc/passwd
root:0:/bin/bash
bin:1:/sbin/nologin
daemon:2:/sbin/nologin
adm:3:/sbin/nologin
lp:4:/sbin/nologin
sync:5:/bin/sync
shutdown:6:/sbin/shutdown

RS:输入记录分隔符,指定输入时的换行符

[root@centos8|8|~]#awk -v RS=' ' '{print $0}' /etc/passwd

ORS:输出记录分隔符,输出时用指定符号代替换行符

[root@centos8|12|~]#awk -v RS=' ' -v ORS='###' '{print $0}' /etc/passwd

NF:字段数量

范例:

[root@centos8 ~]#awk -F:'{print NF}' /etc/fstab
[root@centos8|19|~]#awk -F: '{print $(NF-1)}' /etc/passwd
[root@centos7|28|expect.txt]#ls /misc/cd/Packages/*.rpm |awk -F"." '{print $(NF-1)}'|sort|uniq -c
   2281 i686
   3155 noarch
   4661 x86_64
[root@centos7|37|~]#ss -nt | awk -F"[[:space:]]+|:" '/^ESTAB/{print $(NF-2)}'

范例: 将连接数超过3个以上的IP放入黑名单拒绝访问

[root@centos8|57|script]#cat 5.sh
#!/bin/bash
while :;do
ss -nt | awk -F"[[:space:]]+|:" '/^ESTAB/{print $(NF-2)}'|sort|uniq -c|while read count ip;do
if [ $count -gt 3 ];then
	iptables -A INPUT -s $ip -j REJECT
	fi
done
sleep 10
done

NR:记录编号
范例:

[root@centos8 ~]#awk -F: '{print NR}' /etc/passwd
123
.......
[root@centos8 ~]#awk -F: 'END{print NR}' /etc/passwd
57
[root@centos8 ~]#awk -F: 'BEGIN{print NR}' /etc/passwd

FNR:各文件分别计数,记录号
范例:

awk '{print FNR}' /etc/fstab /etc/inittab
[root@centos8 ~]#awk '{print NR,$0}' /etc/issue /etc/redhat-release 
1 \S
2 Kernel \r on an \m
34 CentOS Linux release 8.0.1905 (Core) 
[root@centos8 script40]#awk '{print FNR,$0}' /etc/issue /etc/redhat-release 
1 \S
2 Kernel \r on an \m
31 CentOS Linux release 8.0.1905 (Core)

FILENAME:当前文件名
范例:

[root@centos8 ~]#awk '{print FILENAME}' /etc/fstab
[root@centos8 ~]#awk '{print FNR,FILENAME,$0}' /etc/issue /etc/redhat-release 
1 /etc/issue \S
2 /etc/issue Kernel \r on an \m
3 /etc/issue 
1 /etc/redhat-release CentOS Linux release 8.0.1905 (Core)

ARGC:命令行参数的个数
范例

[root@centos8 ~]#awk '{print ARGC}' /etc/issue /etc/redhat-release 
3333
[root@centos8 ~]#awk 'BEGIN{print ARGC}' /etc/issue /etc/redhat-release 
3

ARGV:数组,保存的是命令行所给定的各参数
范例:

[root@centos8 ~]#awk 'BEGIN{print ARGV[0]}' /etc/issue /etc/redhat-release 
awk
[root@centos8 ~]#awk 'BEGIN{print ARGV[1]}' /etc/issue /etc/redhat-release 
/etc/issue
[root@centos8 ~]#awk 'BEGIN{print ARGV[2]}' /etc/issue /etc/redhat-release 
/etc/redhat-release
[root@centos8 ~]#awk 'BEGIN{print ARGV[3]}' /etc/issue /etc/redhat-release 
[root@centos8 ~]#

自定义变量(区分字符大小写)
-v var=value
在program中直接定义

awk  -v test='hello gawk' '{print test}' /etc/fstab 
awk  -v test='hello gawk' 'BEGIN{print test}'
awk  'BEGIN{test="hello,gawk";print test}'
awk  -F: '{sex="male";print $1,sex,age;age=18}' /etc/passwd
cat awkscript
{print script,$1,$2}
awk  -F: -f awkscript script="awk" /etc/passwd

动作printf
printf 可以实现格式化输出
必须指定FORMAT
不会自动换行,需要显式给出换行控制符,\n
FORMAT中需要分别为后面每个item指定格式符
格式符:与item一一对应
%c:显示字符的ASCII码
%d, %i:显示十进制整数
%e, %E:显示科学计数法数值
%f:显示为浮点数
%g, %G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%:显示%自身
#[.#] 第一个数字控制显示的宽度;第二个#表示小数点后精度,如:%3.1f
- 左对齐(默认右对齐) 如:%-15s
+   显示数值的正负符号   如:%+d
范例:

awk -F:   '{printf "%s",$1}' /etc/passwd
awk -F:   '{printf "%s\n",$1}' /etc/passwd
awk -F:   '{printf "%-20s %10d\n",$1,$3}' /etc/passwd
awk -F:   '{printf "Username: %s\n",$1}' /etc/passwd
awk -F:   '{printf “Username: %sUID:%d\n",$1,$3}' /etc/passwd
awk -F:   '{printf "Username: %25sUID:%d\n",$1,$3}' /etc/passwd
awk -F:   '{printf "Username: %-25sUID:%d\n",$1,$3}' /etc/passwd

操作符:
算术操作符:
x+y, x-y, x*y, x/y, x^y, x%y
-x:转换为负数
+x:将字符串转换为数值
字符串操作符:没有符号的操作符,字符串连接
赋值操作符:
=, +=, -=, *=, /=, %=, ^=,++, –
范例:

[root@centos8 ~]#awk 'BEGIN{i=0;print ++i,i}'
1 1
[root@centos8 ~]#awk 'BEGIN{i=0;print i++,i}'
0 1

比较操作符:
==, !=, >, >=, <, <=
模式匹配符:
~ 左边是否和右边匹配,包含关系
!~ 是否不匹配

[root@centos8 ~]#awk -F: '$0 ~ /root/{print $1}' /etc/passwd
[root@centos8 ~]#awk -F: '$0 ~ "^root"{print $1}' /etc/passwd
[root@centos8 ~]#awk '$0 !~ /root/'   /etc/passwd
[root@centos8 ~]#awk '/root/'   /etc/passwd
[root@centos8 ~]#awk -F: '$3==0'     /etc/passwd
[root@centos8 ~]#df | awk -F"[[:space:]]+|%" '$0 ~ /^\/dev\/sd/{print $5}'
51
92
[root@centos8 ~]#ifconfig eth0 | awk 'NR==2{print $2}'
10.0.0.8

逻辑操作符:
与&&,或||,非!
范例:

awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd
awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd 
awk -F: '!($3==0) {print $1}' /etc/passwd
awk -F: '!($3>=500) {print $3}' /etc/passwd

条件表达式:
范例:

awk -F: '{$3>=1000?usertype="Common User":usertype="SysUser";printf "%-20s:%12s\n",$1,usertype}' /etc/passwd

模式匹配PATTERN
PATTERN:根据pattern条件,过滤匹配的行,再做处理

  1. 如果未指定:空模式,匹配每一行
    范例:
[root@centos8 ~]#awk -F: '{print $1,$3}' /etc/passwd
  1. /regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来
[root@centos7|125|~]#awk '/^UUID/{print $1}' /etc/fstab
UUID=7e896ac6-4ee4-4533-ad7e-578c71560735
UUID=a063884c-6421-4581-841b-a13cdc73c254
UUID=da6657db-cf66-4ef8-b39f-ff6cf39414f6
UUID=09bcc722-93e2-497c-a51b-480bc92fafc5
UUID=ed7ec688-ffc1-401f-9af9-ab6224d0aab1
UUID=17a95356-e38c-434a-94fc-99819021cc87
[root@centos7|126|~]#awk '!/^UUID/{print $1}' /etc/fstab

#
#
#
#
#
#
#
[root@centos7|127|~]#df | awk '/\/dev\/sd/'
/dev/sda2      104806400  6547656 98258744    7% /
/dev/sda3       52403200    33272 52369928    1% /data
/dev/sdb1         999320     2572   927936    1% /mnt
/dev/sda1        1038336   182952   855384   18% /boot
[root@centos7|128|~]#
  1. relational expression: 关系表达式,结果为“真”才会被处理
    真:结果为非0值,非空字符串
    假:结果为空字符串或0值
    范例:
awk   -F: 'i=1;j=1{print i,j}' /etc/passwd
awk '!0' /etc/passwd ;awk '!1'   /etc/passwd
awk -F: '$3>=1000{print $1,$3}' /etc/passwd
awk -F: '$3<1000{print $1,$3}' /etc/passwd
awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
awk -F: '$NF ~ /bash$/{print $1,$NF}' /etc/passwd
  1. line ranges:行范围
    /pat1/,/pat2/ 不支持直接给出数字格式
[root@centos8 ~]#awk '/^bin/,/^adm/' /etc/passwd
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@centos8 ~]#sed -n '/^bin/,/^adm/p' /etc/passwd
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@centos8 ~]#awk 'NR>=3 && NR<=6{print NR,$0}' /etc/passwd
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
[root@centos8 ~]#sed -n '3,6p' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/syncs

5. BEGIN/END模式

BEGIN{}:仅在开始处理文件中的文本之前执行一次
END{}:仅在文本处理完成之后执行一次

awk -F : 'BEGIN {print "USER USERID"} {print $1":"$3} END{print "END FILE"}' 
/etc/passwd
awk -F: '{print "USER USERID";print $1":"$3} END{print "END FILE"}' /etc/passwd

6. 条件判断if else

语法:
if(condition){statement;…}[else statement]
if(condition1){statement1}else if(condition2){statement2}else{statement3}
范例:

[root@centos7|100|~]#awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd
nfsnobody 65534
yao 1002
linyao 1000
lin 1003
tomcat 1004
test 1005
roob 1006
gordon 1007
mage 1008
wang 1009
liu 1011
lll 1012
xiaohong 1013
xiaobai 1014
baid 1015
asd 1016
tom 1017
cat 1018
[root@centos7|101|~]#awk -F: '{if($NF=="/bin/bash")print $1}' /etc/passwd
root
yao
lin
tomcat
test
roob
mage
wang
liu
lll
xiaohong
xiaobai
baid
asd
tom
cat
[root@centos7|102|~]#awk '{if(NF>5)print $0}' /etc/fstab
# Created by anaconda on Sun Dec  8 16:12:05 2019
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
UUID=7e896ac6-4ee4-4533-ad7e-578c71560735 /                       xfs     defaults        0 0
UUID=a063884c-6421-4581-841b-a13cdc73c254 /boot                   xfs     defaults        0 0
UUID=da6657db-cf66-4ef8-b39f-ff6cf39414f6 /data                   xfs     defaults        0 0
UUID=09bcc722-93e2-497c-a51b-480bc92fafc5 swap                    swap    defaults        0 0
UUID=ed7ec688-ffc1-401f-9af9-ab6224d0aab1 /mnt			ext4     defaults       0 0
UUID=17a95356-e38c-434a-94fc-99819021cc87 swap 			swap  	defaults	0 0
[root@centos7|107|~]#awk -F: '{if($3>=1000){printf "Common user: %s\n",$1}else {printf "root or systemuser : %s\n",$1}}' /etc/passwd
root or systemuser : root
root or systemuser : bin
root or systemuser : daemon
root or systemuser : adm
root or systemuser : lp
root or systemuser : sync
root or systemuser : shutdown
root or systemuser : halt
root or systemuser : mail
root or systemuser : operator
root or systemuser : games
root or systemuser : ftp
root or systemuser : nobody
root or systemuser : systemd-network
root or systemuser : dbus
root or systemuser : polkitd
root or systemuser : sssd
root or systemuser : libstoragemgmt
[root@centos7|113|~]#awk -F: '{if($3>=1000) printf "Common user: %s\n",$1; else printf "root or systemuser : %s\n",$1}' /etc/passwd
[root@centos7|133|~]#df -h|awk -F% '/^\/dev\/sd/{print $1}'| awk '$NF>=10{print $1,$5}'
/dev/sda1 18
[root@centos7|138|~]#df | awk -F"[[:space:]]+|%" '/^\/dev\/sd/{if($5>5)print $1,$5}'
/dev/sda2 7
/dev/sda1 18
[root@centos7|148|~]#awk 'BEGIN{ test=100;if(test>90){print "very good"} else if(test>60){print "good"}else{print "no pass"}}'
very good

switch语句

语法:

switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or 
/REGEXP2/: statement2; ...; default: statementn}

循环while

while (condition) {statement;…}
条件“真”,进入循环;条件“假”,退出循环
使用场景:
对一行内的多个字段逐一类似处理时使用
对数组中的各元素逐一处理时使用

[root@centos7|153|~]#awk 'BEGIN{print length("hello")}'
5
[root@centos7|167|~]#awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-1062.el7.x86_64 31
root=UUID=7e896ac6-4ee4-4533-ad7e-578c71560735 46
ro 2
crashkernel=auto 16
spectre_v2=retpoline 20
rhgb 4
quiet 5
net.ifnames=0 13
linux16 7
/vmlinuz-0-rescue-d85d4d1db0304637b8f76d3d5d3dc54c 50
root=UUID=7e896ac6-4ee4-4533-ad7e-578c71560735 46
ro 2
crashkernel=auto 16
spectre_v2=retpoline 20
rhgb 4
quiet 5
net.ifnames=0 13
[root@centos7 ~]#awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) 
{if(length($i)>=10){print $i,length($i)}; i++}}' /etc/grub2.cfg
/vmlinuz-3.10.0-1062.el7.x86_64 31
root=UUID=bebb9244-bbb8-4c69-9249-54a36c75155e 46
crashkernel=auto 16
net.ifnames=0 13
/vmlinuz-0-rescue-b12558570741487c9328c996e3265b09 50
root=UUID=bebb9244-bbb8-4c69-9249-54a36c75155e 46
crashkernel=auto 16
net.ifnames=0 13
[root@centos7|178|~]#awk 'BEGIN{total=0;i=1;while(i<=100){total+=i;i++}print total}'
5050

循环 do-while

[root@centos7|1|~]#awk 'BEGIN{total=0;i=1;do{total+=i;i++}while(i<=100);print total}'
5050

for循环

语法:

for(expr1;expr2;expr3) {statement;}

特殊语法:能够遍历数组中的元素

for(var in array) {for-body}

范例:

[root@centos7|4|~]#awk 'BEGIN{total=0;for(i=1;i<=100;i++){total+=i};print total}'
5050

范例:

[root@centos7|27|~]#awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}' /etc/grub2.cfg 
linux16 7
/vmlinuz-3.10.0-1062.el7.x86_64 31
root=UUID=7e896ac6-4ee4-4533-ad7e-578c71560735 46
ro 2
crashkernel=auto 16
spectre_v2=retpoline 20
rhgb 4
quiet 5
net.ifnames=0 13
linux16 7
/vmlinuz-0-rescue-d85d4d1db0304637b8f76d3d5d3dc54c 50
root=UUID=7e896ac6-4ee4-4533-ad7e-578c71560735 46
ro 2
crashkernel=auto 16
spectre_v2=retpoline 20
rhgb 4
quiet 5
net.ifnames=0 13

continue和break

范例:

[root@centos7|44|~]#awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i} print sum }'
2500
[root@centos7|46|~]#awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==50)break;sum+=i} print sum }'
1225

next

next 可以提前结束对本行处理而直接进入下一行处理(awk自身循环)

[root@centos7|47|~]#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
sssd 998
colord 996
rpc 32
saslauth 994
rtkit 172
chrony 992

数组

awk的数组为关联数组
可使用任意字符串;字符串要使用双引号括起来
如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”
若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历

[root@centos7|48|~]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["true"];print weekdays["mon"]}'
Monday
范例:
awk '!line[$0]++' dupfile
awk '{!line[$0]++;print $0, line[$0]}' dupfile

判断数组索引是否存在:

array, "y" in array }'
1 0
[root@centos8 ~]#awk 'BEGIN{array["i"]="x"; array["j"]="y" ;if ("i" in array ) 
{print "存在"}else{print "不存在"}}'
存在
[root@centos8 ~]#awk 'BEGIN{array["i"]="x"; array["j"]="y" ;if ("abc" in array ) 
{print "存在"}else{print "不存在"}}'
不存在

若要遍历数组中的每个元素,要使用for循环

for(var in array) {for-body}
[root@centos7|54|~]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";weekdays["wed"]="WENdays";for(i in weekdays){print weekdays[i]}}'
WENdays
Tuesday
Monday
[root@centos7|81|~]#awk -F: '{user[$1]=$3}END{for(i in user){print i,user[i]}}' /etc/passwd
[root@centos7|90|~]#cat ss.log | sed -nr '1!s/^([^0-9]+) .*/\1/p'|sort |uniq -c
     27 ESTAB
[root@centos7|99|~]#ss -ant | awk 'NR!=1{state[$1]++}END{for(i in state){print i,state[i]}}'
LISTEN 16
ESTAB 2
[root@centos8 ~]#netstat -tan | awk '/^tcp/{state[$NF]++}END{for(i in state)
{print i,state[i]}}'
LISTEN 9
SYN_RECV 126
ESTABLISHED 523
FIN_WAIT2 40
[root@centos8 ~]#awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' 
/var/log/httpd/access_log
172.20.0.200 1482
172.20.21.121 2
172.20.30.91 29
172.16.102.29 864
172.20.0.76 1565
172.20.9.9 15
172.20.1.125 463
172.20.61.11 2
172.20.73.73 198
[root@centos8 ~]#awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' access_log 
|sort -k2 -nr|head -3 #k指定第二列来排序
172.20.116.228 4870
172.20.116.208 3429
172.20.0.222 2834

多维数组

[root@centos8 ~]#awk 'BEGIN{
> array[1][1]=11
> array[1][2]=12
> array[1][3]=13
> array[2][1]=21
> array[2][2]=22
> array[2][3]=23
> for (i in array)
>     for (j in array[i])
>         print array[i][j]
> }'
11
12
13
21
22
23

awk函数

awk 的函数分为内置和自定义函数
常见内置函数
数值处理:
rand():返回0和1之间一个随机数
srand():配合rand() 函数,生成随机数的种子
int():返回整数

[root@centos7|105|~]#awk 'BEGIN{srand();print rand()}'
0.32151
[root@centos7|106|~]#awk 'BEGIN{srand();for(i=1;i<=10;i++)print int (rand()*100)}'
49
47
82
59
25
5
82
46
0
54

字符串处理:
length([s]):返回指定字符串的长度
sub(r,s,[t]):对t字符串搜索r表示模式匹配的内容,并将第一个匹配内容替换为s

&代表前面匹配的字符串。

[root@centos8 ~]#echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$1)'
2008-08:08 08:08:08
[root@centos8 ~]#echo "2008:08:08 08:08:08" | awk '{sub(/:/,"-",$1);print $0}'
2008-08:08 08:08:08

gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容

[root@centos8 ~]#echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$0)'
2008-08-08 08-08-08
[root@centos8 ~]#echo "2008:08:08 08:08:08" | awk '{gsub(/:/,"-",$0);print $0}'
2008-08-08 08-08-08

split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个
索引值为1,第二个索引值为2,…

[root@centos8 ~]#netstat -tn | awk 
'/^tcp/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'
10.0.0.1 1
10.0.0.6 1
10.0.0.7 673

system 函数:可以awk中调用shell命令

awk 'BEGIN{system("hostname")}'
awk 'BEGIN{score=100; system("echo your score is " score) }'
[root@centos8 ~]#netstat -tn | awk 
'/^tcp/{split($5,ip,":");count[ip[1]]++}END{for(i in count){if(count[i]>=10)
{system("iptables -A INPUT -s "i" -j REJECT")}}}'

自定义函数

[root@centos8 ~]#cat func.awk
function max(x,y) {
 x>y?var=x:var=y
 return var
}
BEGIN{print max(a,b)}
[root@centos8 ~]#awk -v a=30 -v b=20 -f func.awk
30

awk脚本

[root@centos8 ~]#cat passwd.awk 
{if($3>=1000)print $1,$3}
[root@centos8 ~]#awk -F: -f passwd.awk /etc/passwd
nobody 65534
wang 1000

范例:

去重:
[root@centos7|179|~]# tail /etc/services | awk '{a[$1]++}END{for (v in a)print v}'
isnetserv       48128/udp               # Image Systems Network Services
blp5            48129/udp               # Bloomberg locator
com-bardac-dw   48556/udp               # com-bardac-dw
iqobject        48619/udp               # iqobject
[root@centos7|184|~]#tail /etc/services |awk '{print a[$1]++?$1:"no"}'
no
no
isnetserv
no
blp5
no
com-bardac-dw
no
iqobject
no
[root@centos7|187|~]#tail /etc/services | awk -F '[ /]+' '{a[$1]+=$2}END{for(v in a)print v,a[v]}'
com-bardac-dw 97112
3gpp-cbsp 48049
iqobject 97238
matahari 49000
isnetserv 96256
blp5 96258
[root@centos7|6|~]#tail /etc/services | awk '{a[$1]++}END{for (v in a)print a[v],v}'
2 com-bardac-dw
1 3gpp-cbsp
2 iqobject
1 matahari
2 isnetserv
2 blp5 

内置函数
int()

[root@centos7|10|~]#echo "123abc abc123 123abc123"|xargs -n1 | awk '{print int($0)}'
123
0
123
[root@centos7|11|~]#awk 'BEGIN{print int(10/3)}'
3

rand()

[root@centos7|12|~]#awk 'BEGIN{srand();print rand()}'
0.719291
[root@centos7|13|~]#awk 'BEGIN{srand();print rand()}'
0.719291
[root@centos7|14|~]#awk 'BEGIN{srand();print rand()}'
0.166282
[root@centos7|22|~]#awk 'BEGIN{srand();print int (rand()*10)}'
2
[root@centos7|23|~]#awk 'BEGIN{srand();print int (rand()*10)}'
2
[root@centos7|24|~]#awk 'BEGIN{srand();print int (rand()*10)}'
5
[root@centos7|25|~]#awk 'BEGIN{srand();print int (rand()*10)}'
5
[root@centos7|26|~]#awk 'BEGIN{srand();print int (rand()*10)}'
4

替换:在行前加东西

[root@centos7|30|~]#seq 5 | awk 'NR==2{sub('/.*/',"txt\n&")}{print}'
1
txt
2
3
4
5
[root@centos7|31|~]#seq 5 | awk 'NR==2{sub('/.*/',"&\ntxt")}{print}'
1
2
txt
3
4
5

awk IO语句

[root@centos7|40|~]#seq 5 | awk '/3/{getline;print}'
4    #获取下一条输入的语句

把匹配的下一行加*

[root@centos7|43|~]#seq 5 | awk '/3/{getline;sub(".*","&*");print}'
4*
[root@centos7|45|~]#awk 'BEGIN{while("seq 5"|getline)print}'
1
2
3
4
5

next 当遇到next后面的就不执行

[root@centos7|46|~]#seq 5 | awk '{if ($0==3){next}else{print}}'
1
2
4
5
[root@centos7|49|~]#seq 5 | awk 'NR==1{next}{print $0}'
2
3
4
5
[root@centos7|52|~]#seq 5 | awk 'NR!=1{print $0}'
2
3
4
5

对awk处理后的结果进行操作

[root@centos7|53|~]#tail -n5 /etc/services |awk '{print $2 |"sort"}'
48556/tcp
48556/udp
48619/tcp
48619/udp
49000/tcp

awk需求案例及常见面试题:

对比两个文件:找b文件在a文件相同记录

[root@centos7|73|~]#cat a
1
2
3
4
5
[root@centos7|74|~]#cat b
3
4
5
6
7
[root@centos7|75|~]#awk 'FNR==NR{a[$0];next}{if($0 in a)print $0}' a b
3
4
5
[root@centos7|77|~]#awk 'FNR==NR{a[$0];next}{if($0 in a)print FILENAME,$0}' 
b 3
b 4
b 5
[root@centos7|78|~]#awk 'FNR==NR{a[$0]}NR>FNR{if($0 in a)print $0}' a b
3
4
5
[root@centos7|81|~]#awk 'FNR==NR{a[$0]=1;next}(a[$0]==1)' a b
3
4
5

不同的文件:

[root@centos7|83|~]#awk 'FNR==NR{a[$0]=1;next}!($0 in a)' a b
6
7





[root@centos7|49|~]#seq 5 | awk 'NR==1{next}{print $0}'
2
3
4
5
[root@centos7|52|~]#seq 5 | awk 'NR!=1{print $0}'
2
3
4
5

对awk处理后的结果进行操作

[root@centos7|53|~]#tail -n5 /etc/services |awk '{print $2 |"sort"}'
48556/tcp
48556/udp
48619/tcp
48619/udp
49000/tcp

awk需求案例及常见面试题:

对比两个文件:找b文件在a文件相同记录

[root@centos7|73|~]#cat a
1
2
3
4
5
[root@centos7|74|~]#cat b
3
4
5
6
7
[root@centos7|75|~]#awk 'FNR==NR{a[$0];next}{if($0 in a)print $0}' a b
3
4
5
[root@centos7|77|~]#awk 'FNR==NR{a[$0];next}{if($0 in a)print FILENAME,$0}' 
b 3
b 4
b 5
[root@centos7|78|~]#awk 'FNR==NR{a[$0]}NR>FNR{if($0 in a)print $0}' a b
3
4
5
[root@centos7|81|~]#awk 'FNR==NR{a[$0]=1;next}(a[$0]==1)' a b
3
4
5

不同的文件:

[root@centos7|83|~]#awk 'FNR==NR{a[$0]=1;next}!($0 in a)' a b
6
7




易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!