awk

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运算符

awk_第1张图片
image

运算符例子

(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_第2张图片
image

在记录中搜索一个字段

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

你可能感兴趣的:(awk)