awk工具概述
一、awk编程语言/数据处理引擎
- 基于模式匹配检查输入文本,逐行处理并输出
- 通常用在shell脚本中,获取指定的数据
- 单独用时,可对文本数据做统计
二、命令格式解析
1、主要用法
格式一:
前置命令 | awk [选项] '[条件]{指令}'
格式二:
awk [选项] '[条件]{指令}' 文件
多条语句可以分号分割
print是最常用的指令
2、常用命令选项
-F:指定分隔符,可省略(默认空格或Tab位)
还可识别多种单个的字符,比如以":"或"/"分隔
[root@pubserver ~]# awk -F [:/] '/^root/{print $1,$10}' /etc/passwd
root bash
[root@pubserver ~]# awk -F : '{print $1,$3}' /etc/passwd
root 0
bin 1
daemon 2
adm 3
... ...
三、awk内置变量
有特殊含义,可直接使用
用途 | |
FS | 保存或设置字段分隔符,例如 FS=":" ,与 -F 功能一致 |
$n | 指定分隔的第n个字段,如$1、$3分别表示第1、第3列 |
$0 | 当前读入的整行文本内容 |
NF | 记录当前处理行的字段个数(列数) |
NR | 记录当前已读入行的数量(行数) |
# 输出每行的行号和字段(列)数量
[root@pubserver ~]# awk -F: '{print NR,NF}' /etc/passwd
# 输出每行最后一个字段
[root@pubserver ~]# awk -F: '{print $NF}' /etc/passwd
[root@pubserver ~]# awk -F: '{print "用户名:",$1,"解释器:",$7}' /etc/passwd
用户名: root 解释器: /bin/bash
用户名: bin 解释器: /sbin/nologin
... ...
四、awk过滤的时机
1、在所有行前处理,BEGIN{ }
- 读入第一行文本之前执行
- 一般用来初始化操作
2、逐行处理,{ }
- 逐行读入文本执行相应的处理
- 是最常见的编辑指令块
3、在所有行后处理,END{ }
- 处理完最后一行文本之后执行
- 一般用来输出处理结果
可单独使用,也可以同时一起使用
# 预处理不需要数据文件
[root@pubserver ~]# awk 'BEGIN{a=34;print a+12}'
46
# 统计使用bash的用户个数
[root@pubserver ~]# awk 'BEGIN{x=0}/\<bash$/{x++}END{print x}' /etc/passwd
# 预处理时,行数为0
# 全部处理完成后,行数为已读入文本的行数
[root@pubserver ~]# awk 'BEGIN{print NR}END{print NR}' /etc/passwd
0
50
awk处理条件
一、条件的表现形式
1、正则表达式
/正则表达式/
~ 匹配、!~ 不匹配、\w匹配数字字母下划线、\s匹配空格tab键、\d匹配数字
# 列出以ro开头的用户记录
[root@pubserver ~]# awk -F: '/^ro/{print}' /etc/passwd
# 列出第7个字段不以bash结尾的用户名、登录shell
[root@pubserver ~]# awk -F: '$7!~/bash$/{print $1,$7}' /etc/passwd
2、数值/字符串比较
== 等于、!= 不等于
> 大于、>= 大于或等于
< 小于、<= 小于或等于
# 输出第2行文本
[root@pubserver ~]# awk 'NR==2{print}' /etc/passwd
#输出第2列不是XX的行
[root@pubserver ~]# awk -F: '$2!="XX"{print}' /etc/passwd
# 输出包含2个及以上字段的行
[root@pubserver ~]# awk -F: 'NF>=2{print}' /etc/passwd
3、逻辑比较
&& 逻辑与:期望多个条件都成立
|| 逻辑或:只要有一个条件成立即满足要求
# 列出UID小于2的用户信息
[root@pubserver ~]# awk -F: '$3>=0&&$3<2{print $1,$3}' /etc/passwd
# 列出UID为1或7的用户信息
[root@pubserver ~]# awk -F: '$3==1||$3==7{print $1,$3}' /etc/passwd
4、运算符
+、-、*、/、%
++、--、+=、-=、*=、/=
# 输出奇数行文本
[root@pubserver ~]# awk -F: 'NR%2==1{print NR,$0}' /etc/passwd
# 统计文本的总字段个数
[root@pubserver ~]# awk 'BEGIN{i=0}{i+=NF}END{print i}' /etc/passwd
# 计算能同时被3和13整除的整数个数
[root@pubserver ~]# seq 200 | awk 'BEGIN{i=0}($0%3==0)&&($0%13==0){i++}END{print i}'
5
awk数组
一、数组的定义和使用
1、定义数组
格式:
数组名[下标]=元素值
下标除了可以使用数字,也可以使用字符串,字符串需要使用双引号
2、调用数组
格式:
数组名[下标]
3、遍历数组
用法:
for(变量 in 数组名){print 数组名[变量]}
例:
# 为数组name赋值两个元素,值分别为jim、tom
[root@pubserver ~]# awk 'BEGIN{name[0]="jim";name[1]="tom";print name[0],name[1]}'
jim tom
准备一个测试文档,里面有6行,每行分别是abc、xyz、abc、opq、xyz、abc 然后按照awk逐行处理的工作特点使用awk '{a[$1]++}' shu.txt 走完每一行得到下列结果,但不会输出到屏幕
逐行任务 每行实际执行 执行结果
a[$1]++ a[abc]++ a[abc]=1
a[$1]++ a[xyz]++ a[xyz]=1
a[$1]++ a[abc]++ a[abc]=2
a[$1]++ a[opq]++ a[opq]=1
a[$1]++ a[xyz]++ a[xyz]=2
a[$1]++ a[abc]++ a[abc]=3
awk '{a[$1]++}END{print a["abc"]}' shu.txt #如果要看值,可以输出数组名[下标],由于数组下标不确定,逐行任务运算前可以不用BEGIN任务定义
根据上述操作了解数组可以收集信息,但收集完了之后查看确不方便,可以用for循环实现。方法如下:
awk '{a[$1]++}END{for(i in a){print i,a[i]}}' shu.txt
awk案例
一、针对Web访问日志计算访问量排名
获得结果:客户机的地址、访问次数
按照访问次数排名
利用sort对提取结果排序
-n:按照数值大小排序
-k:针对指定的列进行排序
-r:逆序排序,即降序排序
[root@pubserver ~]# awk '{ip[$1]++}END{for(i in ip){print ip[i],i}}' /var/log/httpd/access_log | sort -nr
二、安全检测
防止远程ssh暴力破解密码
检测安全日志,如果有人登录本机root账户,且总是输入错误的密码,将其找出来
ssh登录日志为/var/log/secure
分析日志文件格式
找出用户名以及密码错误的规律,并提取有效数据
对有效数据进行汇总统计
[root@pubserver ~]# awk '/Failed password for root/{ip[$11]++}END{for(i in ip){print i,ip[i]}}' /var/log/secure
三、监控脚本
编写脚本监控本机各项数据指标:
CPU负载
网卡流量
内存剩余容量
磁盘剩余容量
计算机账户数量
当前登录账户数量
计算机当前开启的进程数量
本机已安装的软件包数量
#!/bin/bash
#while :
#do
clear
free -h | awk '/^Mem:/{print "剩余内存容量是:"$4}'
df -h | awk '/\/$/{print "根分区剩余容量是:"$4}'
awk 'END{print "用户个数是"NR"个"}' /etc/passwd
who | awk 'END{print "登录用户数量是"NR"个"}'
uptime | awk '{print "cpu的15分钟平均负载是:"$NF}'
rpm -qa | awk 'END{print "安装的软件包数量是"NR"个"}'
sleep 3
#done
四、过滤网络流量
[root@pubserver ~]# ifconfig eth0 | awk '/RX p/{print $5}'
RX packets 1495 bytes 110661 (108.0 KiB)
RX errors 0 dropped 13 overruns 0 frame 0
TX packets 348 bytes 42759 (41.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
RX packets 1495:接收的数据包数量为1495个。
bytes 110661 (108.0 KiB):接收的字节数为110661个(108.0 Kibibytes)。
RX errors 0:接收过程中没有发生错误。
dropped 13:有13个数据包在接收过程中被丢弃。
overruns 0:没有发生数据溢出。
frame 0:没有错帧发生。
TX packets 348:发送的数据包数量为348个。
bytes 42759 (41.7 KiB):发送的字节数为42759个(41.7 Kibibytes)。
TX errors 0:发送过程中没有发生错误。
dropped 0:在发送过程中没有数据包被丢弃。
overruns 0:没有发生数据溢出。
carrier 0:在发送过程中没有发生载波错误。
collisions 0:在发送过程中没有碰撞发生。