3 awk的高级用法
3.1 RS 指定行分隔符
awk从文件中读取资料时,将根据RS的定义把资料切割成许多条记录, 而awk一次仅读入一条记录进行处理。内置变量RS的预设值是"\n"。
示例:
指定冒号作为分隔符,打印行号和整行内容。
[root@yuji ~]# echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin [root@yuji ~]# echo $PATH |awk 'BEGIN{RS=":"};{print NR,$0}' //指定冒号作为分隔符,打印行号和整行内容 1 /usr/local/sbin 2 /usr/local/bin 3 /usr/sbin 4 /usr/bin 5 /root/bin [root@yuji ~]# 复制代码
网络异常,图片无法展示
|
3.2 通过管道处理其他命令的结果
示例1:统计行数
方法一:使用内置变量NR,打印最后一行行号
处理完文本后,打印行号,这个行号就是最后一行的行号,也就是行数。(这种方式只适用于输出所有行的情况,即只能统计全文本有多少行)
[root@yuji ~]# echo $PATH |awk 'BEGIN{RS=":"};{print NR,$0}' 1 /usr/local/sbin 2 /usr/local/bin 3 /usr/sbin 4 /usr/bin 5 /root/bin [root@yuji ~]# echo $PATH |awk 'BEGIN{RS=":"};END{print NR}' 5 复制代码
网络异常,图片无法展示
|
方法二:使用"wc -l" 统计行数
使用管道符将命令结果传给"wc -l"。如果在{ }内使用"wc -l" ,一定要加双引号。
[root@yuji ~]# awk -F: '/bash$/{print}' pass.txt root:x:0:0:root:/root:/bin/bash yuji2:x:1000:1000:yuji2:/home/yuji2:/bin/bash nancy:x:1021:1021::/home/nancy:/bin/bash helen:x:1022:1022::/home/helen:/bin/bash [root@yuji ~]# awk -F: '/bash$/{print}' pass.txt |wc -l 4 [root@yuji ~]# awk -F: '/bash$/{print |"wc -l"}' pass.txt 4 复制代码
网络异常,图片无法展示
|
方法三:使用 "grep -c" 统计匹配行的行数。
[root@yuji ~]# grep -c "bash$" pass.txt 4 复制代码
网络异常,图片无法展示
|
示例2:统计内存使用率
free命令可以查看内存使用情况。
使用率=使用的内存数量/总内存数量。
int表示取整数。
[root@yuji ~]# free total used free shared buff/cache available Mem: 999696 310872 319996 7400 368828 491760 Swap: 2097148 0 2097148 [root@yuji ~]# free | awk '/Mem:/ {print $3/$2}' 0.311223 [root@yuji ~]# free | awk '/Mem:/ {print $3/$2*100}' 31.1223 [root@yuji ~]# free | awk '/Mem:/ {print int($3/$2*100)}' 31 [root@yuji ~]# free | awk '/Mem:/ {print int($3/$2*100)"%"}' 31% 复制代码
网络异常,图片无法展示
|
示例3:过滤出CPU的空闲率
top命令可以查看CPU的使用情况。
top -b -n 1 只会输出一次top的结果 不会进行刷新 。
[root@yuji ~]# top -b -n 1 top - 18:45:59 up 4:46, 3 users, load average: 0.04, 0.08, 0.06 Tasks: 149 total, 1 running, 148 sleeping, 0 stopped, 0 zombie %Cpu(s): 0.0 us, 6.2 sy, 0.0 ni, 93.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 s KiB Mem : 999696 total, 317456 free, 311324 used, 370916 buff/cache KiB Swap: 2097148 total, 2097148 free, 0 used. 491288 avail Mem [root@yuji ~]# top -b -n 1 |awk -F, '/Cpu/{print $4}' 100.0 id [root@yuji ~]# top -b -n 1 |awk -F, '/Cpu/{print $4}' |awk '{print $1}' 100.0 [root@yuji ~]# top -b -n 1 |awk -F, '/Cpu/{print $4}' |awk '{print int($1)}' 85 [root@yuji ~]# top -b -n 1 |awk -F, '/Cpu/{print $4}' |awk '{print int($1)"%"}' 86% 复制代码
网络异常,图片无法展示
|
网络异常,图片无法展示
|
3.3 指定输出时的列分隔符
FS 输入时的列分隔符。
OFS 输出内容的列分隔符。($1=$1
用于激活,否则不生效)
[root@yuji ~]# echo "A B C D" A B C D [root@yuji ~]# echo "A B C D" | tr " " "|" A|B|C|D [root@yuji ~]# echo "A B C D" | sed 's/ /|/g' A|B|C|D [root@yuji ~]# echo "A B C D" |awk 'BEGIN{OFS="|"};{$1=$1;print $0}' A|B|C|D 复制代码
网络异常,图片无法展示
|
3.4 使用awk去重(awk数组特性)
在awk中可以定义数组,数组元素的下标值可以是字符串(要加双引号),元素值如果是字符串也要加引号。
1、定义数组。
[root@yuji ~]# awk 'BEGIN{a[0]=10 ;a[1]=20; print a[0]}' 10 [root@yuji ~]# awk 'BEGIN{a[0]=10 ;a[1]=20; print a[1]}' 20 [root@yuji ~]# awk 'BEGIN{a["abc"]=10 ;a["xyz"]=20; print a["abc"]}' 10 复制代码
网络异常,图片无法展示
|
2、打印数组内的所有元素值及对应下标值。
[root@yuji ~]# awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30; for(i in a){print i,a[i]}}' 0 10 1 20 2 30 复制代码
网络异常,图片无法展示
|
3、打印出文件中重复的行,以及重复次数。
[root@yuji ~]# cat test.txt aaa aaa bbb ccc aaa bbb aaa [root@yuji ~]# awk '{a[1]++; print a[1]}' test.txt 1 2 3 4 5 6 7 [root@yuji ~]# awk '{a[$1]++};END{for(i in a){print i,a[i]}}' test.txt aaa 4 ccc 1 bbb 2 复制代码
网络异常,图片无法展示
|
网络异常,图片无法展示
|
拆解分析:
$1第一个字段(列)的值 []里代表列的值 把列的值作为数组的下标去看待 然后去匹配行的内容,匹配一次加1 通过for循环,打印出下标的值和出现的次数 以aaa为例,将aaa作为元素的下标,a["aaa"]初始值为0; 之后每匹配到一次包含aaa的行,a["aaa"]的值就加1; 一共有4行包含aaa,所以最后a["aaa"]=4; 此时下标为aaa,对应的元素值为4。 复制代码
4 案例
通过分析日志 /var/log/secure 查看哪些主机在暴力破解本机服务,如果统计出密码验证失败超过三次(不考虑连续性),就把IP加入到黑名单中 /etc/hosts.deny。
方法一:
#过滤出包含“Failed password”的行,打印第11个字段,且按照数字排序 [root@yuji ~]# awk '/Failed password/{print $11}' /var/log/secure |sort -n 192.168.72.10 192.168.72.10 192.168.72.10 192.168.72.10 192.168.72.192 192.168.72.192 192.168.72.192 #统计重复行出现的次数 [root@yuji ~]# awk '/Failed password/{print $11}' /var/log/secure |sort -n |uniq -c 4 192.168.72.10 3 192.168.72.192 #判断重复的次数如果大于3次,则在IP前加上"sshd:",并将其追加进/etc/hosts.deny文件中 [root@yuji ~]# awk '/Failed password/{print $11}' /var/log/secure |sort -n |uniq -c| awk '$1>3 {print "sshd:"$2}' >>/etc/hosts.deny #查看etc/hosts.deny文件 [root@yuji ~]# cat /etc/hosts.deny # # hosts.deny This file contains access rules which are used to # deny connections to network services that either use # the tcp_wrappers library or that have been # started through a tcp_wrappers-enabled xinetd. # # The rules in this file can also be set up in # /etc/hosts.allow with a 'deny' option instead. # # See 'man 5 hosts_options' and 'man 5 hosts_access' # for information on rule syntax. # See 'man tcpd' for information on tcp_wrappers # sshd:192.168.72.10 复制代码
方法二:利用awk的数组特性
[root@yuji ~]# awk '/Failed password/{a[$11]++};END{for(i in a){print i,a[i]}}' /var/log/secure 192.168.72.10 4 192.168.72.192 3