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
posted @ 2020-09-16 16:27  Bigzhao  阅读(180)  评论(0)    收藏  举报