SHELL DAY4

使用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个

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值