AWK用法

awk工具概述

  • awk编程语言/数据处理引擎
  • 创造者: Aho  Weinberger  Kerninghan
  • 基于模式匹配检查输入文本,获取指定的数据
  • 通常用在shell脚本中,获取指定的数据
  • 单独使用时,可对文本数据做统计
  • 优点就是精确查找,唯一缺点就是不能修改文件

awk命令格式

  • 格式1 : 前置命令 | awk  [选项]   '{(条件)指令}'
  • 格式2 : awk  [选项]  '{(条件)指令}'  被处理的文件
  • 条件类似sed定址符,但是功能更强大

常用命令选项

  • -F  :  指定分隔符,可省略(默认空格或Tab位)
  • -v  var=value  :  自定义变量

常用指令

  • print :  输出

awk内置变量

  • 有特殊含义,可直接使用
awk 内置变量列表
变量含义
FS保存或设置字段分隔符,例如FS=":" ,  与 -F 功能一样
$n指定分隔的第n个字段,如$1.$3分别表示第1列,第3列
$0当前读入的整行文本内容(文本当前行的全部内容)
NF记录当前处理的字段个数(列数)
NR记录当前已读入行的数量(行数)
  • ""  :  常量,一般写提示语
  • \t  :  Tab制表键
  • ,  :  可以实现$n之间的空格效果
[root@proxy mnt]# cat nns  ##以nns作为素材
Hello the worlD
welcome to bEijing
[root@proxy mnt]# awk '{print $1,$2}' nns  ##列出全文第1列和第2列
Hello the
welcome to
[root@proxy mnt]# awk '{print $3,$1}' nns  ##列出全文第3列和第1列
worlD Hello
bEijing welcome
[root@proxy mnt]# awk '{print $0}' nns  ##列出全文
Hello the worlD
welcome to bEijing
[root@proxy mnt]# awk '{print}' nns    ##效果同上
Hello the worlD
welcome to bEijing
[root@proxy mnt]# awk '{print $3,$0}' nns  ##列出第3列和全文
worlD Hello the worlD
bEijing welcome to bEijing
[root@proxy mnt]# cat test  ##以test作为素材
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@proxy mnt]# awk '{print $1}' test  ##默认空格为分隔符,所以输出全文
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@proxy mnt]# awk -F: '{print $1}' test   ##定义:为分隔符,所以输出全文第一列
root
bin
daemon
adm
lp
[root@proxy mnt]# awk -F: '{print $5}' test  ##定义:为分隔符,所以输出全文第5列
root
bin
daemon
adm
lp
[root@proxy mnt]# awk -F: '{print $6}' test  ##定义:为分隔符,所以输出全文第6列
root
/root
/bin
/sbin
/var/adm
/var/spool/lpd
[root@proxy mnt]# awk -F: '{print $7}' test  ##定义:为分隔符,所以输出全文第6列
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
[root@proxy mnt]# awk -F: '/root/{print $1}' test 
root   ##定义:为分隔符,列出有root的行的第1列
[root@proxy mnt]# awk -F: '/^bin/{print $1}' test 
bin    ##定义:为分隔符,列出以bin开头的行的第1列
[root@proxy mnt]# awk -F: '{print $1"的家目录是"$7}' test  ##配合常量显示
root的家目录是/root
bin的家目录是/bin
daemon的家目录是/sbin
adm的家目录是/var/adm
lp的家目录是/var/spool/lpd
[root@proxy mnt]# awk -F: '{print $1"的UID是"$3}' test  ##配合常量显示
root的UID是0
bin的UID是1
daemon的UID是2
adm的UID是3
lp的UID是4
[root@proxy mnt]# awk -F[:/] '{print $10}'  test  ##定义:/为分隔符,所以一行有10列
bash
nologin
nologin
sbin
[root@proxy mnt]# awk -F: '{print NF}' test  ##定义:为分隔符,列出所有行的所有列数
7
7
7
7
7
[root@proxy mnt]# awk -F: '{print NR}' test  ##定义:为分隔符,列出所有行数
1
2
3
4
5
[root@proxy mnt]# awk -F: '{print NR,NF}' test  ##定义:为分隔符,列出所有行数和列数
1 7
2 7
3 7
4 7
5 7

用awk截取接收流量

[root@proxy mnt]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.4.207  netmask 255.255.255.0  broadcast 192.168.4.255
        ether 52:54:00:67:2e:b5  txqueuelen 1000  (Ethernet)
        RX packets 9009  bytes 654078 (638.7 KiB)
        RX errors 0  dropped 3893  overruns 0  frame 0
        TX packets 3303  bytes 399300 (389.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

  • RX : 代表接收流量
  • TX : 代表发送流量
[root@proxy mnt]# ifconfig eth0 | awk '/RX pa/{print $4,$5}'  ##列出接收流量
bytes 676314
[root@proxy mnt]# ifconfig eth0 | awk '/RX pa/{print $4,$5}'  ##列出发送流量
bytes 676894
[root@proxy mnt]# ifconfig eth0 | awk  '/RX p/{print "eth0的接收流量是"$5" 字节"}'
eth0的接收流量是719538字节    ##用常量表示
[root@proxy mnt]# ifconfig eth0 | awk  '/TX p/{print "eth0的发送流量是"$5" 字节"}'
eth0的发送流量是439372字节    ##用常量表示

使用awk提取根分区剩余容量(提取硬盘空间信息)

[root@proxy mnt]# df -h
文件系统        容量  已用  可用 已用% 挂载点
/dev/vda1        30G  1.9G   29G    7% /     
devtmpfs        697M     0  697M    0% /dev
tmpfs           707M     0  707M    0% /dev/shm
tmpfs           707M  8.5M  699M    2% /run
tmpfs           707M     0  707M    0% /sys/fs/cgroup
tmpfs           142M     0  142M    0% /run/user/0

  • 找以/结尾的剩余容量
[root@proxy mnt]# df -h | awk '/\/$/{print "根分区剩余容量是"$3}'
根分区剩余容量是1.9G

查找访问本机密码输入失败的IP信息

  • /var/log/secure  ##这个文件是存放用户远程登录信息的文件

[root@proxy mnt]# tail  /var/log/secure
Jan  8 12:55:58 proxy sshd[13949]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.4.6  user=root
Jan  8 12:55:58 proxy sshd[13949]: pam_succeed_if(sshd:auth): requirement "uid >= 1000" not met by user "root"
Jan  8 12:56:00 proxy sshd[13949]: Failed password for root from 192.168.4.6 port 41394 ssh2
Jan  8 12:56:01 proxy sshd[13949]: pam_succeed_if(sshd:auth): requirement "uid >= 1000" not met by user "root"
Jan  8 12:56:02 proxy sshd[13949]: Failed password for root from 192.168.4.6 port 41394 ssh2
Jan  8 12:56:03 proxy sshd[13949]: pam_succeed_if(sshd:auth): requirement "uid >= 1000" not met by user "root"
Jan  8 12:56:06 proxy sshd[13949]: Failed password for root from 192.168.4.6 port 41394 ssh2
Jan  8 12:56:06 proxy sshd[13949]: error: maximum authentication attempts exceeded for root from 192.168.4.6 port 41394 ssh2 [preauth]
Jan  8 12:56:06 proxy sshd[13949]: Disconnecting: Too many authentication failures [preauth]
Jan  8 12:56:06 proxy sshd[13949]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=192.168.4.6  user=root

 

[root@proxy mnt]# awk '/Failed/{print $11}' /var/log/secure
student
student
student
student
student
student
student
student
student
192.168.4.6
192.168.4.6
192.168.4.6
192.168.4.6

awk处理时机

  • BEGIN{}   在所有行前处理 (指令执行1次)
  • 在读入第一行文本之前执行
  • 一般用来初始化操作
  • {}  逐行处理  (指令执行n次)
  • 逐行读入文本执行相应的处理
  • 是最常见的编辑指令块
  • END{}  在所有行后处理  (指令执行1次)
  • 处理完最后一行文本之后执行
  • 一般用来输出处理结果
  • 格式 :  awk 'BEGIN{指令1次}{逐行任务n次}END{指令1次}'
[root@proxy mnt]# awk  'BEGIN{print "abc"}'   ##列出常量abc一次
abc
[root@proxy mnt]# awk 'BEGIN{print NR}{print "abc"}' test
0
abc
abc
abc
abc
abc   ##执行一次BEGIN后,再逐行处理
[root@proxy mnt]# awk  '{print "abc"}' test  ##全文逐行处理,输出abc
abc
abc
abc
abc
abc
[root@proxy mnt]# awk 'BEGIN{print NR}{print NR}END{print NR}' test
0
1
2
3
4
5
5   ##添加了end任务,多输出最后一行的行号
[root@proxy mnt]# awk 'BEGIN{print NR}{print NR}' test
0
1
2
3
4
5
[root@proxy mnt]# awk 'BEGIN{A=24; print A*2}'   ## 定义变量,做运算
48
[root@proxy mnt]# awk 'BEGIN{A=0}{A++}END{print A}' test 
5      ##定义变量,做逐行运算,最后输出值
[root@proxy mnt]# awk  'BEGIN{print "abc"}{print "xyz"}END{print "789"}' test
abc
xyz
xyz
xyz
xyz
xyz
789   ##列出常量ABC 1次 逐行处理输出xyz 最后列出789
[root@proxy mnt]# awk -F: 'BEGIN{print "abc"}{print $1}END{print NR}' test
abc
root
bin
daemon
adm
lp
5    ##列出常量ABC 1次 逐行处理输出第1列 最后列出逐行处理的行数
[root@proxy mnt]# awk 'BEGIN{print NR}' test  ##输出一次行号,第一行之前的行号,结果为0
0


使用AWK格式化输出文档内容

[root@proxy mnt]# awk -F: 'BEGIN{print "USER\tUID\tHome"}'   ##行前输出
USER    UID    Home
[root@proxy mnt]# awk -F: '{print $1"\t"$3"\t"$6}' test    ##逐行处理
root             0             /root
bin              1             /bin
daemon      2             /sbin
adm            3             /var/adm
lp                4             /var/spool/lpd
[root@proxy mnt]# awk -F: 'END{print "总计"NR"行"}' test   ##行后输出
总计5行
[root@proxy mnt]# awk -F: 'BEGIN{print "USER\tUID\tHome"}{print $1"\t"$3"\t"$6}END{print "总计"NR"行"}' test
USER       UID     Home
root           0        /root
bin             1        /bin
daemon     2       /sbin
adm           3       /var/adm
lp               4       /var/spool/lpd
总计5行                                                        ##组合打印列表


条件的表达形式:

  • 正则设置条件
符号含义
/ /一般写在{}前,匹配正则表达式
~  包含
!~  不包含  
[root@proxy mnt]# awk  '/root/{print}' test  ##如果print后不跟内置变量,可以省略
root:x:0:0:root:/root:/bin/bash
[root@proxy mnt]# awk  '/root/' test   ##效果同上
root:x:0:0:root:/root:/bin/bash
[root@proxy mnt]# awk  '/root|bin/' test   ##列出有root或者有bin的行
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@proxy mnt]# awk  '/^root|^bin/' test  ##列出以root开头或者以bin开头的行
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[root@proxy mnt]# awk -F: '$6~/root/' test  ##列出第6列包含root的行
root:x:0:0:root:/root:/bin/bash
[root@proxy mnt]# awk -F: '$1~/root/' test  ##列出第1列包含root的行
root:x:0:0:root:/root:/bin/bash
[root@proxy mnt]# awk -F: '$1!~/root/' test  ##列出第1列不包含root的行
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

  • 数值/字符串比较
比较符号 :  含义
== 等于
!=不等于
>  大于
>=  大于等于
< 小于
<=  小于等于
[root@proxy mnt]# awk 'NR==2' test  ##列出第2行
bin:x:1:1:bin:/bin:/sbin/nologin
[root@proxy mnt]# awk -F: '$1=="root"' test  ##列出第1列必须是root的行
root:x:0:0:root:/root:/bin/bash
[root@proxy mnt]# awk -F: '$1~/root/' test   ##列出第1列包含root的行,范围广
root:x:0:0:root:/root:/bin/bash
[root@proxy mnt]# awk -F: '$1!="root"' test  ##列出第1列不是root的行
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@proxy mnt]# awk 'NR>2' test     ##列出大于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
[root@proxy mnt]# awk 'NR<=2' test    ####列出小于等于2的行
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[root@proxy mnt]# awk -F: '$3<=10' /etc/passwd  ##列出UID<=10的行
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

  •  逻辑比较
  1. 条件  :  &&  并且  期望多个条件都成立 
  2. 条件  :  ||     或者  只要有一个条件成立即满足要求
[root@proxy mnt]# awk -F: 'NR>=1&&NR<=3' test  ##列出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
[root@proxy mnt]# awk -F: '$3<=5||$3>=1000' /etc/passwd  
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
nginx:x:1000:1000::/home/nginx:/sbin/nologin
lisi:x:1001:1001::/home/lisi:/bin/bash
haha:x:1002:1002::/home/haha:/bin/bash
zhang:x:1003:1003::/home/zhang:/bin/bash
kaka:x:1004:1004::/home/kaka:/bin/bash
tian:x:1005:1005::/home/tian:/bin/bash
titi:x:1008:1008::/home/titi:/bin/bash    ##列出UID小于等于5或者大于等于1000 
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
[root@proxy mnt]# awk -F: '$3<10||$3>1000' /etc/passwd  ##列出UID小于5或者大于1000
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
lisi:x:1001:1001::/home/lisi:/bin/bash
haha:x:1002:1002::/home/haha:/bin/bash
zhang:x:1003:1003::/home/zhang:/bin/bash
kaka:x:1004:1004::/home/kaka:/bin/bash
tian:x:1005:1005::/home/tian:/bin/bash
titi:x:1008:1008::/home/titi:/bin/bash  
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
[root@proxy mnt]# awk -F: '$3<10&&$3>1000' /etc/passwd  ##逻辑错误

列出/etc/hosts/ 文件内以192开头或者以127开头的记录

[root@proxy mnt]# cat /etc/hosts
# ::1        localhost localhost.localdomain localhost6 localhost6.localdomain6
127.0.0.1    localhost localhost.localdomain localhost4 localhost4.localdomain4 
192.168.4.207  www.a.com  
192.168.4.208  www.b.com
[root@proxy mnt]# awk -F. '$1==127||$1==192' /etc/hosts
127.0.0.1    localhost localhost.localdomain localhost4 localhost4.localdomain4 
192.168.4.207  www.a.com  
192.168.4.208  www.b.com


  • 运算符
运算符作用
+加法运算
-减法运算
*乘法运算
/除法运算
%取余运算
++自增1
--自减1
-=减法运算
*=乘法运算
/=除法运算
%=取余运算

[root@proxy mnt]# awk 'BEGIN{print 1+1}'  ##加法运算
2
[root@proxy mnt]# awk 'BEGIN{print 1-1}'  ##减法运算
0
[root@proxy mnt]# awk 'BEGIN{print 1*1}'  ##乘法运算
1
[root@proxy mnt]# awk 'BEGIN{print 2/2}'  ##除法运算
1
[root@proxy mnt]# awk 'BEGIN{print 2%2}'  ##取余运算
0
[root@proxy mnt]# awk 'BEGIN{a=10;print a}'  ##定义变量,输出变量
10
[root@proxy mnt]# awk 'BEGIN{a=10;a++;print a}'  ##定义变量,运算变量,输出变量
11
[root@proxy mnt]# awk 'BEGIN{a=10;a++;print a+=10}'  ##定义变量,运算变量,输出变量
21
[root@proxy mnt]# awk 'BEGIN{a=10;print a%=7}'   ##取余运算
3

列出100以内整数中7的倍数或是含7的数

思路:

  • 1. seq 100    ##输出1-100的数字
  • 2. seq 100 |  awk '$1~/7/'     ##输出1-100数字之内包含7的数字
  • 3.seq 100 | awk '$1%7==0'   ##输出1-100数字之内7的倍数 
[root@proxy mnt]# seq 100 | awk '$1%7==0||$1~/7/'
7
14
17
21
27
28
35
37
42
47
49
56
57
63
67
70
71
72
73
74
75
76
77
78
79
84
87
91
97
98

awk综合脚本示例

  • 编写脚本的任务要求如下:
  • 找到使用bash作登录Shell的本地用户
  • 列出这些用户的shadow密码记录,如图所示

[root@proxy mnt]# vim test08.sh
#!/bin/bash
#这是一个显示能登录shell环境的用户跟用户密码信息的测试脚本
user=`awk -F: '/bash$/{print $1}'  /etc/passwd`
for i in $user
do
    grep $i /etc/shadow | awk -F: '{print $1"--->"$2}'
done
[root@proxy mnt]# bash test08.sh  ##效果如图所示

awk高级应用

awk流程控制

分支结构:

  • 单分支

if(条件){编辑指令}

  • 双分支

if(条件){编辑指令1}else{编辑指令2}

  • 多分支

if(条件){编辑指令1}else if(条件){编辑指令2}...else{编辑指令N}

单分支练习

统计/etc/passwd文件中UID小于或等于1000的用户个数:
[root@proxy mnt]# awk -F: '{if($3<=1000){i++}}END{print i}' /etc/passwd  
24
统计/etc/passwd文件中UID大于1000的用户个数:
[root@proxy mnt]# awk -F: '{if($3>1000){i++}}END{print i}' /etc/passwd
7
统计/etc/passwd文件中登录Shell是“/bin/bash”的用户个数:
[root@proxy ~]# awk -F: '{if($7~/bash$/){i++}}END{print i}'  /etc/passwd
7
[root@proxy mnt]# cat test   ##以test作为素材
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
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@proxy mnt]# awk -F: '{if($3==0){print}}'  test  ##打印UID为0的行
root:x:0:0:root:/root:/bin/bash

双分支练习

分别统计/etc/passwd文件中UID小于或等于1000、UID大于1000的用户个数:
[root@proxy ~]# awk -F: '{if($3>=1000){x++}else{y++}}END{print x,y}' /etc/passwd
8 23
分别统计/etc/passwd文件中登录Shell是“/bin/bash”、 登录Shell不是“/bin/bash”的用户个数:
[root@proxy ~]# awk -F: '{if($7~/bash$/){i++}else{j++}} END{print i,j}' /etc/passwd
7 24

多分支练习

列出UID小于等于10或者大于1000的数量,并统计总数:
[root@proxy ~]# awk -F: 'BEGIN{x=0;y=0;z=0}{if($3<=10){x++}else if($3>1000){y++}else{z++}}END{print x,y,z}' /etc/passwd
9 7 15
加上常量显示:
[root@proxy ~]# awk -F: 'BEGIN{x=0;y=0;z=0}{if($3<=10){x++}else if($3>1000){y++}else{z++}}END{print "UID小于10的数量是"x,"UID大于10的数量是"y,"两者总数是"z}' /etc/passwd
UID小于10的数量是9 UID大于10的数量是7 两者总数是15

awk数组

数组的语法格式:

数组是一个可以存储多个值的变量,具体使用的格式如下:

  • 定义数组的格式:数组名[下标]=元素值
  • 下标可以是数字或者字母或者变量
  • 调用数组的格式:数组名[下标]
  • 遍历数组的用法:for(变量 in 数组名){print 数组名[变量]}。
  • 定义数组后配合for循环可以方便的查看数组所有内容,次过程成为遍历数组
    下标和值可以不用数字

定义数组a自增1,输出结果:
[root@svr5 ~]# awk 'BEGIN{a[0]++;print a[0]}'
1
定义数组a,for循环数组a,由于数组a只有三个下标所以循环3次并输出下标及对应下标的值:
[root@svr5 ~]# awk 'BEGIN{a[0]=0;a[1]=11;a[2]=22; for(i in a){print i,a[i]}}'
0 0
1 11
2 22
定义数组a,下标分别是1和2,然后输出该数组对应下标的值:
[root@proxy ~]# awk 'BEGIN{a[1]=100;a[2]=200;print a[1],a[2]}'
100 200
调用数组的顺序:
[root@proxy ~]# awk 'BEGIN{a[1]=100;a[2]=200;print a[2],a[1]}'
200 100
对定义好的数组做运算:
[root@proxy ~]# awk 'BEGIN{a[1]=100;a[1]++;print a[1]}'
101
定义数组a,for循环遍历数组下标:
[root@proxy ~]# awk 'BEGIN{a[1]=100;a[2]=200;for(i in a){print i}}'
1
2
定义数组a,for循环遍历数组a:
[root@proxy ~]# awk 'BEGIN{a[1]=100;a[2]=200;for(i in a){print i,a[i]}}'
1 100
2 200
定义数组的下标为字母a,需要用""引起来
[root@proxy mnt]# awk 'BEGIN{a["a"]="abc";print a["a"]}'
abc
[root@proxy mnt]# cat abc   以abc作为素材
abc
abc
xyz
opq
xyz
abc
在逐行任务中定义数组a++,for循环遍历数组a,显示下标:
[root@proxy mnt]# awk '{a[$1]++}END{for(i in a){print i}}' abc
opq
abc
xyz
逐行任务,相当于收集数据,然后在END任务中用for循环查看数组的所有内容:
[root@proxy mnt]# awk '{a[$1]++}END{for(i in a){print i,a[i]}}' abc
opq 1
abc 3
xyz 2

以上结果解析:
abc (定义ABC下标)  a[abc]=1  (统计次数为1次) 
abc (已有ABC下标)  a[abc]=2  (统计次数为2次)
xyz (定义xyz下标)  a[xyz]=1  (统计次数为1次)
opt (定义opt下标)  a[opt]=1  (统计次数为1次)
abc (已有ABC下标)  a[abc]=3  (统计次数为3次)
xyz (已有xyz下标)  a[xyz]=2  (统计次数为2次)
abc下标的总数为3次
xyz下标的总数为2次
opt下标的总数为1次

[root@proxy mnt]# cat abc  以abc为素材
abc 192.168.0.1
abc 192.168.0.1
xyz 192.168.0.2
opq 192.168.0.3
xyz 192.168.0.2
abc 192.168.0.1
[root@proxy mnt]# awk '{ip[$2]++}END{for(i in ip){print i}}' abc
192.168.0.1
192.168.0.2
192.168.0.3
[root@proxy mnt]# awk '{ip[$2]++}END{for(i in ip){print i,ip[i]}}' abc
192.168.0.1 3
192.168.0.2 2
192.168.0.3 1

结果解析:
abc 192.168.0.1 (定义192.168.0.1为下标)  a[192.168.0.1]=1  (统计次数为1次) 
abc 192.168.0.1 (已有192.168.0.1下标)    a[192.168.0.1]=2  (统计次数为2次)
xyz 192.168.0.2 (定义192.168.0.2为下标)  a[192.168.0.2]=1  (统计次数为1次)
opt 192.168.0.3 (定义192.168.0.3为下标)  a[192.168.0.3]=1  (统计次数为1次)
abc 192.168.0.1 (已有192.168.0.1下标)    a[192.168.0.2]=2  (统计次数为3次)
xyz 192.168.0.2 (已有192.168.0.2下标)    a[192.168.0.1]=3  (统计次数为2次)
192.168.0.1下标的总数为3次
192.168.0.2下标的总数为2次
192.168.0.3下标的总数为1次

利用sort对提取结果排序

sort 命令: 将文本文件内容加以排序,sort可针对文本文件的内容,以行为单位来排序。

  •  -b   忽略每行前面开始出的空格字符。
  •  -c   检查文件是否已经按照顺序排序。
  •  -d   排序时,处理英文字母、数字及空格字符外,忽略其他的字符。
  •  -f    排序时,将小写字母视为大写字母。
  •  -i    排序时,除了040至176之间的ASCII字符外,忽略其他的字符。
  •  -k    针对指定的列进行排序
  •  -m    将几个排序好的文件进行合并。
  •  -M   将前面3个字母依照月份的缩写进行排序。
  •  -n   依照数值的大小排序。是以数字形式排序
  •  -o  <输出文件>   将排序后的结果存入指定的文件。
  •  -r   以相反的顺序来排序。是降序
  •  -t  <分隔字符>   指定排序时所用的栏位分隔字符。

awk扩展应用

使用awk统计Web访问排名:

在分析Web日志文件时,每条访问记录的第一列就是客户机的IP地址,其中会有很多重复的IP地址。因此只用awk提取出这一列是不够的,还需要统计重复记录的数量并且进行排序。

通过awk提取信息时,利用IP地址作为数组下标,每遇到一个重复值就将此数组元素递增1,最终就获得了这个IP地址出现的次数。

下面以proxy虚拟机作为web服务端:由另外2台虚拟机作为测试机
[root@proxy ~]# rpm -q httpd
httpd-2.4.6-80.el7.centos.x86_64
[root@proxy ~]# systemctl restart httpd
[root@proxy ~]# ss -nutlp |grep :80
tcp    LISTEN     0      128       *:80                    *:*                   users:(("httpd",pid=1037,fd=3),("httpd",pid=1036,fd=3),("httpd",pid=1035,fd=3),("httpd",pid=1034,fd=3),("httpd",pid=1033,fd=3),("httpd",pid=1032,fd=3))
[root@proxy ~]# cd /var/log/httpd
[root@proxy httpd]# ls  ##httpd服务的访问日志
access_log  error_log
利用真机,其他虚拟机进行访问
[root@proxy ~]# curl localhost
[root@proxy ~]# curl 192.168.4.5
[root@proxy2 ~]# curl 192.168.4.5
[root@proxy2 ~]# curl 192.168.4.5
[root@proxy3 ~]# for i in {1..20}
> do
> curl 192.168.4.5
> done
查看网站的被访问次数,与对应的IP地址,然后降序排列:
[root@proxy httpd]# awk '{ip[$1]++}END{for(i in ip){print ip[i],i}}' /var/log/httpd/access_log | sort -nr
1 127.0.0.1
2 192.168.4.6
20 192.168.4.7

编写监控脚本

本案例要求编写脚本,实现计算机各个性能数据监控的功能,具体监控项目要求如下:
1.CPU负载
2.网卡流量
3.内存剩余容量
4.磁盘剩余容量
5.计算机账户数量
6.当前登录账户数量
7.计算机当前开启的进程数量
8.本机已安装的软件包数量

 1.查看性能数据的命令

  • 1.CPU负载 : [root@proxy ~]# uptime   
  • 2.网卡流量 : [root@proxy ~]# ifconfig eth0 
  • 3.内存剩余容量 :  [root@proxy ~]# free    
  • 4.磁盘剩余容量 :  [root@proxy ~]# df     
  • 5.计算机账户数量 : [root@proxy ~]# wc -l /etc/passwd
  • 6.当前登录账户数量 : [root@proxy ~]# who |wc -l 
  • 7.计算机当前开启的进程数量 : [root@proxy ~]# ps aux | wc -l 
  • 8.本机已安装的软件包数量 : [root@proxy ~]# rpm -qa |wc -l   

2.用awk进行处理1-5

  • 1.[root@proxy mnt]# uptime | awk '{print "CPU的平均负载是"$8 $9 $10}'  ##列数请参照实际情况,此为案例
  • 2.[root@proxy mnt]#  ifconfig eth0 |awk -F[\(\)] '/RX p/{print "eth0的接收流量是"$2}'
  • 2.[root@proxy mnt]# ifconfig eth0 |awk -F[\(\)] '/TX p/{print "eth0的接收流量是"$2}'
  • 3.[root@proxy mnt]#  free -m | awk '/Mem:/{print "当前主机剩余内存空间"$4"MB"}'
  • 4.[root@proxy mnt]#  df -h |awk '/\/$/{print "主机根分区剩余空间是"$4}'
  • 5.[root@proxy mnt]#  awk 'END{print "本机账户数量是"NR"个"}' /etc/passwd |wc -l

3.编写监控脚本

[root@proxy mnt]# vim test09.sh 
#!/bin/bash
#这是一个简单的监控测试脚本
while :
do
uptime | awk '{print "CPU的平均负载是"$8 $9 $10}'
ifconfig eth0 |awk -F[\(\)] '/RX p/{print "eth0的接收流量是"$2}'
ifconfig eth0 |awk -F[\(\)] '/TX p/{print "eth0的发送流量是"$2}'
free -m | awk '/Mem:/{print "当前主机剩余内存空间"$4"m"}'
df -h |awk '/\/$/{print "主机根分区剩余空间是"$4}'
awk  'END{print "本机账户数量是"NR"个"}' /etc/passwd
u=`who | wc -l`
 echo "主机账户数量是$u个"
p=`ps aux | wc -l`
 echo "当前主机开启的进程数量是$p个"
r=`rpm -qa | wc -l`
echo "当前主机已安装的软件包的数量是$r个"
sleep 3
clear  ##清屏,效果跟Ctrl+l相同
done
[root@proxy mnt]# bash test09.sh 
CPU的平均负载是0.14,0.05,0.05
eth0的接收流量是947.0 KiB
eth0的发送流量是922.1 KiB
当前主机剩余内存空间1184m
主机根分区剩余空间是29G
当前主机用户数量是31个
当前主机登录账户数量是2个
当前主机开启的进程数量是93个
当前主机已安装的软件包的数量是440个

编写安全检测脚本

防止远程ssh暴力破解密码,具体监控项目要求如下:

  • 检测ssh登录日志,如果远程登陆账号名错误3次,则屏蔽远程主机的IP
  • 检测ssh登录日志,如果远程登陆密码错误3次,则屏蔽远程主机的IP

1.过滤帐户名失败的命令(登陆日志文件为/var/log/secure)

  • [root@proxy mnt]# awk '/Invalid user/{print $11}' /var/log/secure   ##列出登录失败的账号
  • [root@proxy mnt]# awk '/Invalid user/{ip[$11]++}END{for(i in ip){print ip[i],i}}' /var/log/secure  ##统计次数

2. 过滤密码失败的命令

  • [root@proxy mnt]# awk '/Failed/{print $11}' /var/log/secure  ##列出密码登录失败的账号
  • [root@proxy mnt]# awk '/Failed/{ip[$11]++}END{for(i in ip){print ip[i],i}}' /var/log/secure ##统计次数

3.编写安全检测脚本

[root@proxy mnt]# vim a.sh 
#!/bin/bash
#这是一个简单的安全检测脚本
p=`awk '/Failed/{ip[$11]++}END{for(i in ip){print ip[i],i}}' /var/log/secure |awk '$1>3{print $2}'`
[ -z "$p" ] || echo "有人尝试登录服务器!!!!相关信息是$p" | mail -s test root

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值