awk介绍
awk取行
//找谁 {}干啥
awk 'NR==3' file #取第三行
awk 'NR<3' file #取第一第二行
awk 'NR>3' file #取第三行以后
awk 'NR>2&&NR<6' file #第三行到第五行
awk 'NR==1||NR==6' file #第1行和第6行
awk '!/root/' #不要root 取反
awk取列
awk '{动作}' file
#取出第五列 awk的列数 从第一列开始:$1 默认分隔符是空格和tab键
awk '{print $1}' /etc/hosts #第一列
awk '{print $2}' /etc/hosts #第二列
#可以指定分隔符!
awk -F
head -1 /etc/passwd|awk -F ":" '{print $1}'
#在没有空格和tab的情况下 以:分割
#如果列数输出结果 你想让她空开显示 使用,或者“里面什么都可以”,不加:也可以 Fd oldboy中以d分开
head -1 /etc/passwd|awk -F ":" '{print $1,$3}'
head -1 /etc/passwd|awk -F ":" '{print $1"=="$3}'
awk变量
NF #最后一列
[root@oldboy ~]# cat 1.txt
inet 10.0.0.200/24
qqq aaa ccc bbb
aaa ccc
111 222 3333
666
[root@oldboy ~]# awk '{print NF}' 1.txt (多少列)
2
4
2
3
1
[root@oldboy ~]# awk '{print $NF}' 1.txt (最后一列是什么)
10.0.0.200/24
bbb
ccc
3333
666
[root@oldboy ~]# awk '{print NF-2}' 1.txt (多少列-2)
0
2
0
1
-1
[root@oldboy ~]# awk '{print $(NF-2)}' 1.txt $0 就是全输出
inet 10.0.0.200/24
aaa
aaa ccc
111
读取文件前
'BEGIN'
[root@shell /server/scripts]# awk 'BEGIN{print "ok"}'
ok
[root@shell /server/scripts]# awk 'BEGIN{FS=":"}{print $1}' pass
root
bin
daemon
adm
lp
显示你想要干的事 (前面的命令控制了 输出几行 结果是后面print管的 与前面看的啥内容无关)
pass里是五行内容 后面该干啥干啥 和pass文件没关系
[root@shell /server/scripts]# cat pass |awk '{print 10*10}'
100
100
100
100
100
[root@shell /server/scripts]# cat pass |awk '{print "ok"}'
ok
ok
ok
ok
ok
[root@shell /scripts]# cat pass |awk 'BEGIN{print "HEHE"}{print "ok"}END{print "lalala"}'
HEHE
ok
ok
ok
ok
ok
lalala
使用制表符和字符串
[root@shell /server/scripts]# awk -F":" '{print "username: "$1",\t UID:"$3}' pass
username: root, UID:0
username: bin, UID:1
username: daemon, UID:2
username: adm, UID:3
username: lp, UID:4
awk运算符
运算符例子
(a+=5) == (a=a+5)
awk 'BEGIN{a=5}{print a+=5}' #10
逻辑运算符
awk 'BEGIN{a=1;b=2;print (a
正则运算符
awk 'BEGIN{a="100testaaa";if(a~/100/){print "has 100"}}'
算数运算符
说明,所有用作算术运算符 进行操作,操作数自动转为数值,所有非数值都变为 0
awk 'BEGIN{a="B";printa++,++a}' #0 2
awk 'BEGIN{a="11abc";print a+=1}' #12
三目运算符
awk 'BEGIN{a="B";print a=="B"?"a is B":"a not B"}' #a is B
计算和
[root@lb03 ~]# seq 100 |awk '{i+=$1}END{print i}'
5050
运算表达式
行处理前
[root@lb03 ~]# awk 'BEGIN{print 10 ^ 10}'
10000000000
#awk 自定义内部变量
[root@lb03 ~]# awk -va=10 -vb=20 'BEGIN{print a ^ b}'
100000000000000000000
#把用户的uid的值乘于10小于100的显示出来
[root@lb03 ~]# awk -F: '$3 * 10 < 100{print $1}' passwd
bin
daemon
adm
lp
sync
shutdown
halt
mail
提前把root改为10了
[root@lb03 ~]# awk -F: '/root/{print $3 + 10}' passwd
20
21
[root@lb03 ~]# awk -F: '/root/{print $3 - 10}' passwd
0
1
[root@lb03 ~]# awk -F: '/root/{print $3 * 10}' passwd
100
110
[root@lb03 ~]# awk -F: '/root/{print $3 / 10}' passwd
1
1.1
[root@lb03 ~]# awk -F: '/root/{print $3 % 10}' passwd 取余
0
1
[root@lb03 ~]# awk -F: '/root/{print $3 ^ 10}' passwd
10000000000
25937424601
awk 内置变量
RS | 输入记录的分隔符 ,默认是回车 |
---|---|
变量名 | 属性 |
$0 | 当前记录(当前行) |
n | 字段序号(分隔符做出的分隔是一个字段) |
FS | 输入字段的分隔符 一般在BEGIN块里 ,也可以使用 awk -F"" 指定分隔符 |
NF | 当前记录的字段个数 就是总共有多少列 $NF是最后一列 |
NR | 已经读出的记录数目 也就是行号 从1开始 (NR,$0) |
OFS | 输出字段分隔符 默认是 空格 |
输出记录的分隔符, 默认是 换行符 |
指定分隔符FS
awk 'BEGIN{FS=":"}{print $1,$2,$3}' /etc/passwd #指定分隔符为 : ,然后读取列
[root@shell /server/scripts]# awk -F: '{print $1,$2,$3}' pass
root x 0
bin x 1
daemon x 2
adm x 3
lp x 4
awk 'BEGIN{FS="[[:space:]+]"}{print $1,$2,$3}' /etc/passwd #分隔符为一个或多个 空格
案例:取ip
[root@lb03 ~]# ip a s eth0
2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:b9:7e:75 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.4/24 brd 10.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:feb9:7e75/64 scope link
valid_lft forever preferred_lft forever
[root@lb03 ~]# ip a s eth0 | awk -F '[ /]' 'NR==3{print $3}'
init前面还有空格 所以$3匹配不到
[root@lb03 ~]# ip a s eth0 | awk 'NR==3{print $2}'
10.0.0.4/24
[root@lb03 ~]# ip a s eth0 | awk -F '[ /]' 'NR==3{print $5}'
init
[root@lb03 ~]# ip a s eth0 | awk -F '[ /]' 'NR==3{print $6}'
10.0.0.4
[root@lb03 ~]# ip a s eth0 | awk -F '[ /]*' 'NR==3{print $3}'
10.0.0.4
[root@lb03 ~]# cat ip.log
2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:b9:7e:75 brd ff:ff:ff:ff:ff:ff
/ /inet 10.0.0.4/24 brd 10.0.0.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:feb9:7e75/64 scope link
valid_lft forever preferred_lft forever
[root@lb03 ~]# awk -F '[ /]*' 'NR==3{print $3}' ip.log
10.0.0.4 前面就算有空格有/ 你分隔符指定的空格/ 所以空格和/会被看成整体
记录数量NR
ifconfig eth0|awk 'NR==2{print $2}' #IP地址
显示行号 FNR
[root@lb03 ~]# awk '{print FNR,$0}' passwd hosts
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
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
1 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
2 ::1 localhost localhost6 localhost6.localdomain6
字段数量NF
awk 'BEGIN{FS=":"}{print NF}' pass #查看一个字段有几列 (之前用FS 制定了字段分隔符)
[root@shell /server/scripts]# awk 'BEGIN{FS=":"}{print NF}' pass
7
7
7
7
7
awk -F ":" 'NF==8{print $0}' /etc/passwd #当一个字段有8列的时候输出整行
记录分隔符RS
awk 'BEGIN{RS=":"}{print}' /etc/passwd #把所有:替换成回车
[root@shell /server/scripts]# awk 'BEGIN{RS=":"}{print}' pass
root
x
0
0
root
/root
/bin/bash
bin
x
1
1
bin
指定字段分隔符OFS
awk 'BEGIN {FS=":";OFS="#"}{print $1,$2,$3}' /etc/passwd
#输出
root#x#0
bin#x#1
daemon#x#2
adm#x#3
lp#x#4
sync#x#5
shutdown#x#6
[root@lb03 ~]# awk -F: '{print $7":"$2":"$3":"$4":"$5":"$6":"$1}' passwd |head -1
/bin/bash:x:0:0:root:/root:root
[root@lb03 ~]# awk 'BEGIN{FS=":";OFS=":"}{print $7,$2,$3,$4,$5,$6,$1}' passwd |head -1
/bin/bash:x:0:0:root:/root:root
[root@lb03 ~]# awk 'BEGIN{FS=":";OFS="#########"}{print $7,$2,$3,$4,$5,$6,$1}' passwd |head -1
/bin/bash#########x#########0#########0#########root#########/root#########root
[root@lb03 ~]# awk -F: -vOFS=":" '{print $7,$2,$3,$4,$5,$6,$1}' passwd |head -1
/bin/bash:x:0:0:root:/root:root
指定记录分隔符ORS
awk 'BEGIN{ORS="\t"}{print}' /etc/passwd #把默认的回车替换成了制表符
格式化输出
[root@lb03 ~]# awk -F: '{print "用户为:"$1" 对应的UID号为:"$3}' passwd
用户为:root 对应的UID号为:0
用户为:bin 对应的UID号为:1
用户为:daemon 对应的UID号为:2
用户为:adm 对应的UID号为:3
用户为:lp 对应的UID号为:4
用户为:sync 对应的UID号为:5
用户为:shutdown 对应的UID号为:6
用户为:halt 对应的UID号为:7
用户为:mail 对应的UID号为:8
[root@lb03 ~]# date |awk '{print "今年是:"$NF"年"}'
今年是:2019年
%s 字符类型
%d 数值类型
15字符
- 左对齐
\n 不带就飞了
[root@shell /server/scripts]# awk -F: '{printf "%-15s %-10s %-15s\n",$1,$2,$3}' pass
root x 0
bin x 1
daemon x 2
adm x 3
lp x 4
awk的模式动作
模式
[root@lb03 ~]# awk '/root/' passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
模式 + 动作
[root@lb03 ~]# awk -F: '/root/{print $1}' passwd
root
operator
动作
[root@lb03 ~]# awk -F: '{print $1}' passwd
root
bin
daemon
adm
lp
awk正则表达式
在记录中搜索一个字段
awk '/root/{print }' /etc/passwd #搜索*root* 在记录中
输出第5条记录中包含root的字段
awk -F: '$5~/root/{print }' /etc/passwd
[root@lb03 ~]# awk -F: '$4 ~/98/' passwd
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
[root@lb03 ~]# awk -F: '/98/' passwd
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
ntp:x:98:38::/etc/ntp:/sbin/nologin
#取反
[root@lb03 ~]# awk -F: '$4 !~/98/' passwd
root:x:0:0:root:/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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
[root@lb03 ~]# awk -F: '$3 ~/^9/' passwd
nobody:x:99:99:Nobody:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
ntp:x:98:38::/etc/ntp:/sbin/nologin
[root@lb03 ~]# awk -F: '$4 ~/^3/' passwd
ntp:x:98:38::/etc/ntp:/sbin/nologin
比较表达式
root@lb03 ~]# awk 'NR==1' passwd
root:x:0:0:root:/root:/bin/bash
[root@lb03 ~]# awk 'NR<2' passwd
root:x:0:0:root:/root:/bin/bash
#是管理员用户的打印出来
[root@lb03 ~]# awk -F: '$1 == "root"' passwd
root:x:0:0:root:/root:/bin/bash
[root@lb03 ~]# awk -F: '$3 == 0' passwd
root:x:0:0:root:/root:/bin/bash
#打印系统其它用户
[root@lb03 ~]# awk -F: '$3 > 0' 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@lb03 ~]# awk -F: '$3 > 0 && $3 < 1000 {print $1}' passwd
bin
daemon
adm
lp
#双条件判断是否管理员用户
[root@lb03 ~]# awk -F: '$1 == "root" && $3 == 0 ' passwd
root:x:0:0:root:/root:/bin/bash
[root@lb03 ~]# vim passwd
[root@lb03 ~]# awk -F: '$1 == "root" && $3 == 0 ' passwd
[root@lb03 ~]# awk -F: '$1 == "root" && $3 == 0 ' passwd
[root@lb03 ~]# awk -F: '$1 == "root" || $3 == 0 ' passwd
root:x:10:0:root:/root:/bin/bash
[root@lb03 ~]# awk -F: '$1 == "root" || $3 == 10 ' passwd
root:x:10:0:root:/root:/bin/bash
[root@lb03 ~]# awk -F: '$1 == "root" && $3 == 10 ' passwd
root:x:10:0:root:/root:/bin/bash
#统计系统用户有多少个
[root@lb03 ~]# awk -F: '$3 > 0 && $3 < 1000 {print $1}' passwd |wc -l
21
[root@lb03 ~]# awk -F: '$3 > 0 && $3 < 1000 {i++}END{print i}' passwd
21
#统计普通用户数量
[root@lb03 ~]# awk -F: '$3 >= 1000 {i++}END{print i}' passwd
10
案例:打印系统内存的使用率
[root@lb03 ~]# free -m
total used free shared buff/cache available
Mem: 974 92 721 13 161 708
Swap: 1023 0 1023
[root@lb03 ~]# free -m |awk '/^Mem/{print $3/$2*100"%"}'
9.44559%
布尔表达式
awk 'bool{action}' filename // bool?action:pass
awk 'BEGIN{FS=":"}$1=="root"{print }' /etc/passwd #如果 第一个字段是 root 则输出
复合用法
awk -F: '$1=="root"||$4==0{print}' /etc/passwd
awk-if,while
if
打印当前管理员用户名称
[root@shell /server/scripts]# awk -F: '{if($3==0){print $1 " is adminisitrator"}}' /etc/passwd
root is adminisitrator
打印系统管理员数量和其他用户数量
[root@shell ~]# awk -F: '{if($3==0){i++}else {j++}}END{print "管理员数量为:"i;print "其他用户数量为:"j}' /etc/passwd
管理员数量为:1
其他用户数量为:33
统计系统用户
[root@shell /server/scripts]# awk -F: '{if($3>0 && $3<1000){i++}}END{print i}' /etc/passwd
24
统计普通用户数量
[root@shell /server/scripts]# awk -F: '{if($3>999){i++}}END{print i}' /etc/passwd
3
三个加一起
[root@shell ~]# awk -F: '{if($3==0){i++}else {if($3>0 && $3<1000){j++}else {o++}}}END{print "管理员用户数量是:"i;print "系统用户数量是:"j;print "普通用户数量是:"o}' /etc/passwd
管理员用户数量是:1
系统用户数量是:24
普通用户数量是:9
>,<,=
第四列大于五 输出整行
[root@shell /server/scripts]# awk -F: '{if($4>5) print $0}' pass
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
如果第三列值大于5 输出整行 否则输出第一行
[root@shell /server/scripts]# awk -F: '{if($3>5){print $0} else {print $1}}' pass
root
bin
daemon
adm
lp
第三列*2大于五 输出整行
[root@shell /server/scripts]# awk -F: '$3*2 >5 {print $0}' pass
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
循环
创建10个用户
[root@lb03 ~]# awk 'BEGIN{for(i=1;i<=10;i++){print "useradd old"i}}' |bash
改时间
[root@lb03 ~]# awk 'BEGIN{for(i=1;i<15;i++){print "date -s 2019/11/"i" && touch file-"i".txt"}}' |bash
while
[root@shell /server/scripts]# awk 'BEGIN{i=1;while(i<=10){print i; i++}}'
1
2
3
4
5
6
7
8
9
10
创建用户
[root@lb03 ~]# awk 'BEGIN{i=1;while(i<10){print "useradd new"i;i++}}' |bash
数组
求和
[root@lb03 ~]# seq 100 |awk '{qiuhe+=$1}END{print qiuhe}'
5050
[root@lb03 ~]# awk '{zong+=$10}END{print zong}' access.log
1308567366
取次数
+= 表示求和
++ 统计次数
shell数量
[root@shell ~]# awk -F: '{shell[$NF]++}END{for(i in shell)print i "出现了"shell[i]"次"}' /etc/passwd
/bin/sync出现了1次
/bin/bash出现了9次
/sbin/nologin出现了22次
/sbin/halt出现了1次
/sbin/shutdown出现了1次
tcp十一种状态数量
[root@shell ~]# ss -ant |awk 'NR>1{state[$1]++}END{for (i in state)print i "出现了"state[i]"次"}'
LISTEN出现了6次
ESTAB出现了1次
性别数量
[root@shell ~]# awk -F: '{shell[$1]++}END{for(i in shell)print i "出现了"shell[i]"次"}' set.txt
ip访问次数
[root@shell ~]# awk '{ip[$1]++}END{for (i in ip)print i "出现了"ip[i]"次"}' access.log |sort -nrk2|column -t|head
统计系统日志secure.log,破解密码失败的ip的次数
[root@lb03 ~]# awk '/Failed password/{ips[$(NF-3)]++}END{for (i in ips)print i,ips[i]}' secure.log |sort -rnk2 |head |column -t
218.65.30.25 68652
218.65.30.53 34326
218.87.109.154 21201
112.85.42.103 18065
112.85.42.99 17164
统计访问日志中每个ip的访问次数和每个ip对应返回的字节数量。
[root@lb03 ~]# awk '{ips[$1]++;he[$1]+=$10}END{for (i in ips)print i,ips[i],he[i]}' access.log |sort -rnk2 |head |column -t
139.226.172.217 16033 749869585
47.102.42.79 1041 16462
180.95.238.82 994 154136
113.140.249.33 727 105270
每个IP访问状态码数量
[root@lb03 ~]# awk '{count[$1" "$9]++}END{for (i in count)print i,count[i]}' access.log |sort -rnk3 |column -t|grep '139.226.172.217'
139.226.172.217 200 14731
139.226.172.217 304 805
139.226.172.217 404 193
139.226.172.217 302 108