一、awk命令
●可以对文本实现精确搜索并输出 ,逐行处理
用法:
1,前置指令 | awk 选项 条件 指令
2,awk 选项 条件 指令 被处理文档
选项:-F 定义分隔符
指令:print 打印、输出
条件:/字符串/
内置变量:$1第一列 $2第二列 $3第三列 ...$0 所有列 NR行号 NF 列号
1.1 准备素材
[root@test1 ~]# echo "hello the world" > abc.txt
[root@test1 ~]# echo "welcome to hangzhou" >> abc.txt
[root@test1 ~]# cat abc.txt #准备素材1
hello the world
welcome to hangzhou
[root@test1 ~]# cp /etc/passwd user #准备素材2
1.2 awk命令运用
[root@test1 ~]# awk '{print}' abc.txt #输出所有
hello the world
welcome to hangzhou
[root@test1 ~]# awk '/to/{print}' abc.txt #输出有to的那行
welcome to hangzhou
[root@test1 ~]# awk '{print $2}' abc.txt #输出所有行的第2列
the
to
[root@test1 ~]# awk '/to/{print $1}' abc.txt #输出有to的那行的第1列
welcome
[root@test1 ~]# awk '{print $0}' abc.txt #输出所有行所有列
hello the world
welcome to hangzhou
[root@test1 ~]# awk '{print $0,$1}' abc.txt #输出所有行所有列,第1列
hello the world hello
welcome to hangzhou welcome
[root@test1 ~]# awk '{print NR}' abc.txt #输出所有行的行号
1
2
[root@test1 ~]# awk '{print NR,$0}' abc.txt #输出所有行的行号,所有列
1 hello the world
2 welcome to hangzhou
[root@test1 ~]# awk '{print NR,NF}' abc.txt #输出所有行的行号,列号(有几列)
1 3
2 3
[root@test1 ~]# awk '/^bin/{print NR}' user #找以bin开头的行,显示该行的行号
2
[root@test1 ~]# awk '/^bin/{print NR,$0}' user #找以bin开头的行,显示该行的行号,所有列
2 bin:x:1:1:bin:/bin:/sbin/nologin
[root@test1 ~]# awk '{print NF}' user #输出所有行的列号(每行有几列)
1
1
1
1
1
[root@test1 ~]# awk -F: '{print $1}' user #文档中如果没有空格,可以用F修改分隔符
root
bin
daemon
adm
lp
[root@test1 ~]# awk -F: '{print $1,$6}' user #使用冒号作为列的分隔符,显示第1、6列
root /root
bin /bin
daemon /sbin
adm /var/adm
lp /var/spool/lpd
[root@test1 ~]# awk -F: '{print $1" 的家目录是 "$6}' user #还可以输出常量,加双引号即可
root 的家目录是 /root
bin 的家目录是 /bin
daemon 的家目录是 /sbin
adm 的家目录是 /var/adm
lp 的家目录是 /var/spool/lpd
[root@test1 ~]# awk -F: '{print $1" 的解释器是 "$7}' user
root 的解释器是 /bin/bash
bin 的解释器是 /sbin/nologin
daemon 的解释器是 /sbin/nologin
adm 的解释器是 /sbin/nologin
lp 的解释器是 /sbin/nologin
1.3 收集根分区剩余容量
[root@test1 ~]# df -h | awk '/\/$/{print $4}' #使用df -h 作为前置指令交给awk处理找到以/结尾的行,并输出第4列
46G
[root@test1 ~]# df -h | awk '/\/$/{print "根分区剩余容量是"$4}' #然后加常量输出
根分区剩余容量是46G
1.4 收集网卡流量信息
[root@test1 ~]# ifconfig ens192 | awk '/RX p/{print "ens192网卡接收的数据量是"$5"字节"}'
ens192网卡接收的数据量是107209996字节
[root@test1 ~]# ifconfig ens192 | awk '/TX p/{print "ens192网卡发送的数据量是"$5"字节"}'
ens192网卡发送的数据量是22857468字节
二、awk的条件
2.1 /字符串/
●可以使用正则 ~ 包含 !~不包含
[root@test1 ~]# awk -F: '$6~/root/{print}' user #输出第6列包含root的行
root:x:0:0:root:/root:/bin/bash
[root@test1 ~]# awk -F: '$6~/bin/{print}' user #输出第6列包含bin的行
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@test1 ~]# awk -F: '$6!~/bin/{print}' user #输出第6列不包含bin的
root:x:0:0:root:/root:/bin/bash
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
2.2 使用数字或者字符串
== != > >= < <=
[root@test1 ~]# awk -F: '$3<3{print}' user #输出第3列小于3的行
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@test1 ~]# awk -F: '$3<=3{print}' user #输出第3列小于等于3的行
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
[root@test1 ~]# awk -F: 'NR==2{print}' user #输出第2行
bin:x:1:1:bin:/bin:/sbin/nologin
[root@test1 ~]# awk -F: 'NR>2{print}' user #输出行号大于2的行
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
2.3 逻辑组合
&&并且 ||或者
[root@test1 ~]# awk -F: 'NR==2||NR==4{print}' user #找行号是2或者4的行
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@test1 ~]# awk -F: 'NR==2||NR==40{print}' user #如果只有一个条件满足就显示一个
bin:x:1:1:bin:/bin:/sbin/nologin
#找第7列包含bash并且第3列小于等于500的行
[root@test1 ~]# awk -F: '$7~/bash/&&$3<=500{print}' user
root:x:0:0:root:/root:/bin/bash
[root@test1 ~]# awk 'NR==2&&NR==4{print}' user #找行号既是2又是4的行,不存在,无输出
[root@test1 ~]# awk -F: '$7~/bash/&&NR<=3{print}' user #找第7列包含bash并且行号是1~3的
root:x:0:0:root:/root:/bin/bash
[root@test1 ~]# awk -F: '$7~/bash/||NR<=3{print}' user #找第7列包含bash或者行号是1~3的
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
2.4 awk处理时机
●可以执行额外任务
BEGIN任务 执行1次,读取文档之前执行
逐行任务 执行n次,读取文档时执行
END任务 执行1次,读取文档之后执行
用法格式:BEGIN{ 任务1 }{ 任务2 }END{ 任务3 }
[root@test1 ~]# awk -F: 'BEGIN{print "ok"}{print $1}END{print "ok"}' user
ok
root
bin
daemon
adm
lp
ok
[root@test1 ~]# awk 'BEGIN{print NR}{print NR}END{print NR}' user
0
1
2
3
4
5
5
1)利用awk处理时机,输出下列内容
单命令输出
[root@test1 ~]# awk 'BEGIN{print "User\tUID\tHome"}' #第1步输出表头信息
User UID Home
[root@test1 ~]# awk -F: '{print $1"\t"$3"\t"$6}' user #第2步输出内容
root 0 /root
bin 1 /bin
daemon 2 /sbin
adm 3 /var/adm
lp 4 /var/spool/lpd
[root@test1 ~]# awk 'END{print "总计"NR"行" }' user #第3步输出结尾
总计5行
合并命令输出
[root@test1 ~]# awk -F: 'BEGIN{print "User\tUID\tHome"}{print $1"\t"$3"\t"$6}END{print "总计"NR"行"}' user
User UID Home
root 0 /root
bin 1 /bin
daemon 2 /sbin
adm 3 /var/adm
lp 4 /var/spool/lpd
总计5行
三、awk综合脚本
●使用awk数组+for循环实现高级搜索
数组:相当于可以存储多个值的特殊变量
数组名[下标] = 下标对应的值
3.1 案例运用
[root@test1 ~]# awk 'BEGIN{a[1]=10;a[2]=20;print a[2],a[1]}' #使用awk测试数组,首先创建数组a,下标1对应值是10,下标2对应值是20,然后输出下标是2与下标是1的值
20 10
[root@test1 ~]# awk 'BEGIN{a["abc"]="abcabc";a["xyz"]="xyzxyz";print a["xyz"]}' #数组的下标和值都可以不是数字,测试时加双引号即可
xyzxyz
以上信息是手工输入,实际情况中通常是从文档收集
准备一个文档,里面有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
3.2 awk和for循环结合
根据上述操作得知使用数组可以收集信息,但收集完了之后查看确不方便,可以用for循环实现。方法如下:
for(变量名 in 数组名){print 变量名} #这个格式可以查看数组的所有下标
awk '{a[$1]++}END{for(i in a){print i,a[i]}}' shu.txt #使用逐行任务与数组收集文档shu.txt中的信息,然后在END任务中使用for循环显示所有数组a的下标与值
awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' /var/log/httpd/access_log #将上述的文件替换成网站的日志,就可以最终用来查看日志得到可以得到哪个ip来访以及来访的次数
awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' /var/log/httpd/access_log | sort -nr -k 2 #使用sort命令增加排序功能,-n是以数字形式排序,-r是降序, -k是指定为第几列排序
3.3 综合脚本案例
◆编写脚本,可以查看系统的各种参数信息
[root@test1 ~]# vim xtcs.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@test1 ~]# chmod u+x xtcs.sh
[root@test1 ~]# ./xtcs.sh
剩余内存容量是6.6G
根分区剩余容量是46G
用户总数是34个
登录用户数量是2个
cpu的15分钟平均负载是0.05
安装的软件包数量是413个
剩余内存容量是6.6G
根分区剩余容量是46G
用户总数是34个
登录用户数量是2个
cpu的15分钟平均负载是0.05
安装的软件包数量是413个
循环执行
........
........
........