使用awk提取文本
步骤一:awk的基本用法
1)基本操作方法
格式1:awk [选项] '[条件]{指令}' 文件
格式2:前置指令 | awk [选项] '[条件]{指令}'
其中,print 是最常用的编辑指令;若有多条编辑指令,可用分号分隔。
Awk过滤数据时支持仅打印某一列,如第2列、第5列等。
处理文本时,默认将空格、制表符作为分隔符。
条件可以用/ /的方式,与sed类似
awk常用内置变量:
$0 文本当前行的全部内容
$1 文本的第1列
$2 文件的第2列
$3 文件的第3列,依此类推
NR 文件当前行的行号
NF 文件当前行的列数(有几列)
[root@sv7 ~]# vim abc.txt
hello the world
ni hao ma
12:00 2088-9-04
[root@sv7 ~]# awk '{print}' abc.txt #输出所有数据
[root@sv7 ~]# awk '/the/{print}' abc.txt #输出有the的那行
[root@sv7 ~]# awk '/the/{print $1}' abc.txt #输出有the的那行的第1列
[root@sv7 ~]# awk '/the/{print $1,$3}' abc.txt #输出有the的那行的第1,3列
[root@sv7 ~]# awk '{print $0}' abc.txt #输出所有行所有列
[root@sv7 ~]# awk '{print $0,$1}' abc.txt #输出所有行所有列,第1列
[root@sv7 ~]# awk '{print NR}' abc.txt #输出所有行的行号
[root@sv7 ~]# awk '{print NR,$0}' abc.txt #输出所有行的行号,所有列
[root@sv7 ~]# awk '{print NR,NF}' abc.txt #输出所有行的行号,列号(有几列)
再使用之前的user文档测试
[root@sv7 ~]# awk '/^root/{print NR}' user #找以root开头的行,显示该行的行号
[root@sv7 ~]# awk '/^root/{print NR,$0}' user #找以root开头的行,显示该行的行号,所有列
[root@sv7 ~]# awk '{print NF}' user #输出所有行的列号(每行有几列)
2)选项 -F 可指定分隔符
[root@sv7 ~]# awk -F: '{print $1}' user #文档中如果没有空格,可以用F修改分隔符
[root@sv7 ~]# awk -F: '{print $1,$6}' user #使用冒号作为列的分隔符,显示第1、6列
awk还识别多种单个的字符,比如以“:”或“/”分隔
[root@sv7 ~]# awk -F [:/] '/^root/{print $1,$10}' user
awk的print指令不仅可以打印变量,还可以打印常量
[root@sv7 ~]# awk -F: '{print $1" 的家目录是 "$6}' user #输出常量,加双引号即可
[root@sv7 ~]# awk -F: '{print $1" 的解释器是 "$7}' user
步骤二:利用awk提取本机系统数据
1)收集根分区剩余容量
[root@sv7 ~]# df -h | awk '/\/$/{print $4}' #使用df -h 作为前置指令交给awk处理找到以/结尾的行,并输出第4列
[root@sv7 ~]# df -h | awk '/\/$/{print "根分区剩余容量是"$4}' #然后加常量输出
2)收集网卡流量信息
RX为接收的数据量,TX为发送的数据量。packets以数据包的数量为单位,bytes以字节为单位:
[root@sv7 ~]# ifconfig eth0 | awk '/RX p/{print "eth0网卡接收的数据量是"$5"字节"}'
[root@sv7 ~]# ifconfig eth0 | awk '/TX p/{print "eth0网卡发送的数据量是"$5"字节"}'
步骤三:格式化输出信息
1)awk处理的时机
awk会逐行处理文本,支持在处理第一行之前做一些准备工作,以及在处理完最后一行之后做一些总结性质的工作。在命令格式上分别体现如下:
awk [选项] '[条件]{指令}' 文件
awk [选项] 'BEGIN{指令} {指令} END{指令}' 文件
BEGIN{ } 行前处理,读取文件内容前执行,指令执行1次
{ } 逐行处理,读取文件过程中执行,指令执行n次
END{ } 行后处理,读取文件结束后执行,指令执行1次
格式化输出/etc/passwd文件
要求: 格式化输出passwd文件内容时,要求第一行为列表标题,中间打印用户的名称、UID、家目录信息,最后一行提示一共已处理文本的总行数,效果如图所示:
[root@sv7 ~]# awk -F: '{print "用户名:",$1, "UID是:",$3}' /etc/passwd
用户名: root UID是: 0
用户名: bin UID是: 1
用户名: daemon UID是: 2
[root@sv7 ~]# awk -F: 'BEGIN{print "用户名 UID 家目录"} {print $1,$3,$6} END{print "系统中 有:"NR,"个用户"}' /etc/passwd
用户名 UID 家目录
root 0 /root
bin 1 /bin
daemon 2 /sbin
...
系统中有: 33 个用户
此时结果已经显示,但是格式没有对齐,不太好看,可以使用column -t 调整一下排版
[root@sv7 ~]# awk -F: 'BEGIN{print "用户名 UID 家目录"} {print $1,$3,$6} END{print "系统中 有:",NR,"个用户"}' /etc/passwd | column -t
用户名 UID 家目录
root 0 /root
bin 1 /bin
daemon 2 /sbin
awk处理条件
步骤一:认识awk处理条件的设置
1)使用正则设置条件
/正则/ ~ 包含 !~不包含
[root@sv7 ~]# cat /etc/passwd > user #准备素材文件
[root@sv7 ~]# awk '/root/{print}' user #找含有root的行打印
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@sv7 ~]# awk -F: '$1~/root/{print}' user #输出第1列包含root的行
root:x:0:0:root:/root:/bin/bash
[root@sv7 ~]# awk -F: '$7~/bash/{print}' user #输出第7列包含bash的行
[root@sv7 ~]# awk -F: '$7!~/bash/{print}' user #输出第7列不包含bash的行
2)使用数值/字符串比较设置条件
比较符号:==(等于) !=(不等于) >(大于)
\>=(大于等于) <(小于) <=(小于等于)
[root@sv7 ~]# awk -F: '$1=="root"{print}' user #精准匹配第1列是root的行
[root@sv7 ~]# awk -F: '$3==3{print}' user #输出第3列uid是3的行
[root@sv7 ~]# awk -F: '$3>=1000{print}' user #输出第3列uid大于等于1000的行
[root@sv7 ~]# awk -F: 'NR==2{print}' user #输出第2行,NR是行号
[root@sv7 ~]# awk -F: 'NR>20{print}' user #输出行号大于20的行
3)逻辑测试条件;&&并且;||或者
[root@sv7 ~]# awk -F: '$3>10&&$3<15{print}' user #找第3列uid大于10 小于15的行
[root@sv7 ~]# awk -F: 'NR==2||NR==4{print}' user #找行号是2或者4的行
4)数学运算,BEGIN可以单独使用,不依赖于文件,后面可以不跟文件名
[root@sv7 ~]# awk 'BEGIN{print 1.5+2}'
3.5
[root@sv7 ~]# awk 'BEGIN{print 3*3}'
9
[root@sv7 ~]# awk 'BEGIN{print 12/3}'
4
[root@sv7 ~]# awk 'BEGIN{print 12-3}'
9
[root@sv7 ~]# awk 'BEGIN{print 11%3}'
2
[root@sv7 ~]# awk 'NR%2==0{print NR,$0}' user #在条件中使用运算,找到将行号除以2余数等于0的行,然后输出该行的行号和所有列,相当于输出偶数行
awk数组
步骤一:awk数组
1)数组的语法格式
数组是一个可以存储多个值的变量,具体使用的格式如下:
定义数组的格式:数组名[下标]=元素值
调用数组的格式:数组名[下标]
[root@sv7 ~]# awk 'BEGIN{a[1]=10;a[2]=20;print a[2],a[1]}' #使用awk测试数组,创建数组a,下标1对应值是10,下标2对应值是20,然后输出下标是2与下标是1的值
注意:awk数组的下标除了可以使用数字,也可以使用字符串,字符串需要使用双引号:
[root@sv7 ~]# awk 'BEGIN{a["abc"]="tom";a["xyz"]="jim";print a["xyz"]}'
此时打印出的值只有一个,如果想要把所有的值打印还需要再次写上a["abc"],如果值特别多就不方便,那么可以使用循环解决问题
for(变量名 in 数组名){print 变量名} #这个格式可以查看数组的所有下标
[root@sv7 ~]# awk 'BEGIN{a["abc"]="tom";a["xyz"]="jim";for(i in a){print i}}' #此时取的是a的下标,如果想要取值可以使用下面命令
abc
xyz
[root@sv7 ~]# awk 'BEGIN{a["abc"]="tom";a["xyz"]="jim";for(i in a){print a[i]}}'
tom
jim
也可以加上i把下标和值打印出来
[root@sv7 ~]# awk 'BEGIN{a["abc"]="tom";a["xyz"]="jim";for(i in a){print i,a[i]}}'
abc tom
xyz jim
awk扩展应用
通过awk提取信息时,利用IP地址作为数组下标,每遇到一个重复值就将此数组元素递增1,最终就获得了这个IP地址出现的次数。
针对文本排序输出可以采用sort命令,相关的常见选项为-r、-n、-k。其中-n表示按数字顺序升序排列,而-r表示反序,-k可以指定按第几个字段来排序。
步骤一:统计Web访问量排名,分步测试、验证效果如下所述。
1)提取IP地址及访问量,统计每个人访问了多少次
[root@sv7 ~]# vim log.txt
192.168.88.5 /a.html
192.168.88.5 /c.png
192.168.77.5 /x.php
192.168.88.9 /a.mp3
192.168.160.5 /u.doc
172.16.88.5 /e.html
[root@sv7 ~]# awk '{ip[$1]++}END{for(i in ip){print ip[i],i }}' log.txt #数组名称可以自定义其他的,通过awk数组+for循环查看日志中哪个ip来访过以及来访的次数
2)对第1)步的结果根据访问量排名
[root@sv7 ~]# awk '{ip[$1]++}END{for(i in ip){print ip[i],i}}' log.txt | sort -nr #使用sort命令增加排序功能,-n是以数字形式排序,-r是降序
安全检测
检测登录者的IP,检测安全日志,登录root且密码错误就输出对方IP
步骤一:准备工作
1)/var/log/secure是安全日志,如果有人登陆时输入错误密码的话信息会记录下来,这种信息可以用awk抓取出来,方法如下:
[root@sv7 ~]# awk '/Failed password for root/{ip[$11]++}END{for(i in ip){print i,ip[i]}}' /var/log/secure #统计安全日志中访问root账户且密码输入错误的ip地址与次数
编写监控脚本
编写脚本,实现计算机各个性能数据监控的功能,具体监控项目看实际操作内容
编写shell脚本,利用awk截取系统各种信息,如内存与硬盘剩余空间大小、账户数量等,并每隔3秒循环显示一次
步骤一:准备工作
1)部分常用命令
[root@sv7 ~]# uptime #查看CPU负载
[root@sv7 ~]# ifconfig eth0 #查看网卡流量
[root@sv7 ~]# free #查看内存信息
[root@sv7 ~]# df #查看磁盘空间
[root@sv7 ~]# wc -l /etc/passwd #查看计算机账户数量
[root@sv7 ~]# who |wc -l #查看登录账户数量
[root@sv7 ~]# rpm -qa |wc -l #查看已安装软件包数量
步骤二:编写参考脚本
1)脚本内容如下:
[root@sv7 ~]# vim test01.sh
#!/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@sv7 ~]# chmod +x test01.sh
[root@sv7 ~]# ./test01.sh
剩余内存容量是164Mi
根分区剩余容量是19G
用户总数是33个
登录用户数量是1个
cpu的15分钟平均负载是0.00
安装的软件包数量是364个
150

被折叠的 条评论
为什么被折叠?



