步骤一:awk的基本用法
基本操作方法
格式1:awk [选项] '[条件]{指令}' 文件
格式2:前置指令 | awk [选项] '[条件]{指令}'
其中print 是最常用的编辑指令;若有多条编辑指令,可用分号分隔。
Awk过滤数据时支持仅打印某一列,如第2列、第5列等。
处理文本时,默认将空格、制表符作为分隔符。
条件可以用/ /的方式,与sed类似
awk常用内置变量:
$0 文本当前行的全部内容
$1 文本的第1列
$2 文件的第2列
$3 文件的第3列,依此类推
NR 文件当前行的行号
NF 文件当前行的列数(有几列)
练习一
cat abc.txt
hello the world
welcome to beijing #准备素材
awk '{print}' abc.txt #输出所有
awk '/to/{print}' abc.txt #输出有to的那行
awk '{print $2}' abc.txt #输出所有行的第2列
awk '/to/{print $1}' abc.txt #输出有to的那行的第1列
awk '{print $0}' abc.txt #输出所有行所有列
awk '{print $0,$1}' abc.txt #输出所有行所有列,第1列
awk '{print NR}' abc.txt #输出所有行的行号
awk '{print NR,$0}' abc.txt #输出所有行的行号,所有列
awk '{print NR,NF}' abc.txt #输出所有行的行号,列号(有几列)
练习二
准备素材user
awk '/^bin/{print NR}' user #找以bin开头的行,显示该行的行号
awk '/^bin/{print NR,$0}' user #找以bin开头的行,显示该行的行号,所有列
awk '{print NF}' user #输出所有行的列号(每行有几列)
awk -F: '{print $1}' user #文档中如果没有空格,可以用F修改分隔符
awk -F: '{print $1,$6}' user #使用冒号作为列的分隔符,显示第1、6列
awk -F [:/] '/^root/{print $1,$10}' user
awk -F: '{print $1" 的家目录是 "$6}' user #输出常量,加双引号即可
awk -F: '{print $1" 的解释器是 "$7}' user
步骤二:利用awk提取本机系统数据
df -h | awk '/\/$/{print $4}' #使用df -h 作为前置指令交给awk处理找到以/结尾的行,并输出第4列
df -h | awk '/\/$/{print "根分区剩余容量是"$4}' #然后加常量输出
ifconfig eth0 | awk '/RX p/{print "eth0网卡接收的数据量是"$5"字节"}'
ifconfig eth0 | awk '/TX p/{print "eth0网卡发送的数据量是"$5"字节"}'
步骤三:格式化输出信息
awk会逐行处理文本,支持在处理第一行之前做一些准备工作,以及在处理完最后一行之后做一些总结性质的工作。在命令格式上分别体现如下
awk [选项] '[条件]{指令}' 文件
awk [选项] 'BEGIN{指令} {指令} END{指令}' 文件
BEGIN{ } 行前处理,读取文件内容前执行,指令执行1次
{ } 逐行处理,读取文件过程中执行,指令执行n次
END{ } 行后处理,读取文件结束后执行,指令执行1次
awk -F: 'BEGIN{print "start"}{print $1}END{print "over"}' user
awk 'BEGIN{print NR}{print NR}END{print NR}' user
格式化输出/etc/passwd文件
awk 'BEGIN{print "User\tUID\tHome"}' #第1步输出表头信息
awk -F: '{print $1"\t"$3"\t"$6}' user #第2步输出内容
awk 'END{print "总计"NR"行" }' user #第3步输出结尾
awk -F: 'BEGIN{print "User\tUID\tHome"}{print $1"\t"$3"\t"$6}END{print "总计"NR"行"}' user #合在一起写
步骤四:awk处理条件
awk -F: '$6~/root/{print}' user #输出第6列包含root的行
awk -F: '$6~/bin/{print}' user #输出第6列包含bin的行
awk -F: '$6!~/bin/{print}' user #输出第6列不包含bin的行
awk -F: '$3<3{print}' user #输出第3列小于3的行
awk -F: '$3<=3{print}' user #输出第3列小于等于3的行
awk -F: 'NR==2{print}' user #输出第2行
awk -F: 'NR>2{print}' user #输出行号大于2的行
awk -F: 'NR>=3&&NR<=5{print}' user #找行号是3~5行
awk -F: 'NR==2||NR==4{print}' user #找行号是2或者4的行
awk -F: 'NR==2||NR==40{print}' user #如果只有一个条件满足就显示一个
awk -F: '$7~/bash/&&$3<=500' user #找第7列包含bash并且第3列小于等于500的行
awk 'NR==2&&NR==4' user #找行号既是2又是4的行,不存在,无输出
awk -F: '$7~/bash/&&NR<=3' user #找第7列包含bash并且行号是1~3的
awk -F: '$7~/bash/||NR<=3' user #找第7列包含bash或者行号是1~3的
awk 'NR%2==0{print NR,$0}' user #在条件中使用运算,找到将行号除以2余数等于0的行,然后输出该行的行号和所有列,相当于输出偶数行
步骤五:awk数组
数组的语法格式
数组是一个可以存储多个值的变量,具体使用的格式如下:
定义数组的格式:数组名[下标]=元素值
调用数组的格式:数组名[下标]
awk 'BEGIN{a=10;a=20;print a}' #首先测试普通变量
awk 'BEGIN{a[1]=10;a[2]=20;print a[2],a[1]}' #使用awk测试数组,创建数组a,下标1对应值是10,下标2对应值是20,然后输出下标是2与下标是1的值
awk 'BEGIN{a["abc"]="abcabc";a["xyz"]="xyzxyz";print a["xyz"]}' ##awk数组的下标除了可以使用数字,也可以使用字符串,字符串需要使用双引号
步骤六:awk扩展应用
统计Web访问量排名
awk '{ip[$1]++}END{for(i in ip){print ip[i],i }}' /var/log/httpd/access_log #数组名称可以自定义其他的,通过awk数组+for循环查看日志中哪个ip来访过以及来访的次数
awk '{ip[$1]++}END{for(i in ip){print ip[i],i}}' /var/log/httpd/access_log | sort -nr #使用sort命令增加排序功能,-n是以数字形式排序,-r是降序
安全检测
awk '/Failed password for root/{ip[$11]++}END{for(i in ip){print i,ip[i]}}' /var/log/secure #统计安全日志中访问root账户且密码输入错误的ip地址与次数
编写监控脚本
#!/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