awk使用小结

2017/11/9



awk博大精深,本文仅持续更新在工作中频繁使用的方法。



【AWK】
使用逻辑判断 if else
在逻辑处理过程中调用外部指令,并使用 getline 得到输出,最终赋值给变量
#!/bin/bash
#
# 2017/11/9
# decode etcdv3 output k/v with base64

### "key": "foo",
### "value": "bar",

ETCDCTL_API=3 etcdctl get -w json --prefix '/' |jq '.' |awk -F'"' '{
    if ($2=="key") {
        "base64 -d<<< \""$4"\"" |getline $4
        print $1"\""$2"\""$3"\""$4"\""$5
    } else if ($2=="value") {
        "base64 -d<<< \""$4"\"" |getline s_decode
        if (index(s_decode, "{") != 0) {
            print $1"\""$2"\""$3s_decode$5
        } else {
            print $0
        }
    } else {
        print $0
    }
}'


在处理数据前,先赋值几个变量
awk -v dt_a=`date +%s` -v dt_b=`date +%s` 'BEGIN{if(dt_a==dt_b) {print 1} else {print 0}}'



截取一行数据中指定的2个数字做加减乘除运算:
请仔细对比下述3种方式的差异
[root@tvm01 asset]# echo 'aaa 1%, bbb 2%, ccc 3%, ddd 4%' |sed -r 's/.*([0-9]).*([0-9]).*([0-9]).*([0-9]).*/\1+\2/' |bc
3
[root@tvm01 asset]# echo 'aaa 1%, bbb 2%, ccc 3%, ddd 4%' |awk -F'%,' '{print $1$2}' |sed 's/[a-z]//g' |awk '{print $1+$2}'
3
[root@tvm01 asset]# echo 'aaa 1%, bbb 2%, ccc 3%, ddd 4%' |awk -F'[ %,]' '{print $2+$6}'                                   
3


去掉空格:
awk '{ result=gensub(/ /,"",1);print result }'

打印某一段内容:
awk '{print $7}' access.log

统计IP数量:
awk '{cs[$1]+=1} END {for(c in cs) print cs[c], c}' access.log |sort -nr

打印最后一列:
awk '{print $8 " " $NF} ' access.log

统计大小:
awk '{print $10 "  " $1 "  " $7}' access.log|awk '{B+=$1} END {print B/1024/1024 " MB"}'

统计TCP状态:
netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'

统计日志中http状态码:
zcat 2013-07-15-0000-2330_test.company.com.*|awk '{print $9}'|sort|uniq -c|sort -nr|more

统计日志格式最后一行是源站IP的对应数据:
zcat 2013-07-15-*|awk '$7~/test.company.com/{print $NF}'|sort|uniq -c|sort -nr|head

统计日志中第2行超过1M大小的URL,并打印第2行的大小和第3行的URL
awk '$2~/.*M/ {print $2"\t"$3}' access.log

统计日志中18点访问test.company.com,状态码为200的数据,打印响应时间和源站地址:
zcat 2013-07-15-18*|grep test.company.com|awk '$9=="200"{print $(NF-7),$NF}'|sort|uniq -c|sort -nr|more

统计延时超过100ms的请求:
zcat 2013-07-15-18*|grep test.company.com|awk '$9=="0"&&$(NF-7)>100 {print $(NF-7)}'|sort|uniq -c|sort -nr|more

NR:整个脚本当前已经读过的记录数,就是行号,从1开始。随着所读文件的数目,一直累加。
FNR:同NR,不过是相对于当前在读的文件记录数。每开始读一个文件时,从1开始累加,相当于行号。读完一个文件后就会清0,新的文件又会从1开始。
http://in.sdo.com/?p=1054

统计http code为502的数量,IP
假设有以下文件:
cs.502 : 统计了出现502的次数和IP,格式为“次数  IP”
cs.502.ip : 从cs.502中筛选出IP,格式为“IP”
cs.502.country : 利用qqwry做IP到地理位置的转换,格式为“IP  地理位置”
现在的需求是,把cs.502和cs.502.country合并

awk 'NR==FNR {a[$2]=$0;next} NR>FNR {print a[$1] " "$2}' cs.502 cs.502.country >cs.502.log

计算http code 海外相对全部的占比是多少
test.all 的内容是:
46255 0
967 504
218 502

test.oversea 的内容是:
1171 0
408 504
205 502

awk 'NR==FNR {a[$2]=$1;next} NR>FNR {printf "%.2f% ", $1/a[$2]*100;print $2}' test.all test.oversea 
2.53% 0
42.19% 504
94.04% 502

计算百分比:
echo 55 4001638 |awk '{printf "%.4f%\n",$1/$2*100}'

根据后3位来排序:
1231234214329049203
4239049230492039402
3209402394023940234
awk '{print $0,substr($0,length($0)-2,3)}' x.txt |sort -n -k 2 | awk '{print $1}'
sed -r 's/(.*)((.){3})/\1|\2/' test.txt |sort -n -k 2 -t \| |sed 's/|//g'


去重 
awk '!a[$1]++' test.log

展示df的简单版本,只显示磁盘分区和对应的used的值:
df -h |sed '1d' |egrep -v ""/dev/shm"|"/dev/mapper"" |awk '{print $NF"\t"$(NF-1)}' |while read a b; do echo "$a used: $b"; done

统计swap占用的进程:
for i in `cd /proc;ls |grep "^[0-9]"|awk ' $0 >100'` ;do awk '/Swap:/{a=a+$2}END{print '"$i"',a/1024"M"}' /proc/$i/smaps ;done |sort -k2nr |head

统计最小值,使用 BEGIN 来初始化变量,if做循环判断,END输出结果
test.log:
96.3738
95.72002499999999
96.78004999999999
95.8748
96.146125
96.7587
96.11826666666666
96.69625
95.88227499999999
96.4341


# cat test.log |awk 'BEGIN {min=100} {if ($1<min) {min=$1;x=$1}} END {print x}'
95.72002499999999

统计服务器的cpu,内存和磁盘信息,截取小数点,四舍五入
echo `hostname` |cut -d'.' -f1 \
&& echo `cat /proc/cpuinfo |grep processor |wc -l`'C' |tr '\n' '|' \
&& cat /proc/meminfo |grep 'MemTotal' |awk '{m=$(NF-1)/1024/1024;print m"G"}' |tr '\n' '|' \
&& lsblk -o SIZE,TYPE,MOUNTPOINT |grep -E '(data|disk1)' |awk '{print $1}' \
&& echo && lsblk -o SIZE,TYPE,MOUNTPOINT && free -m |grep Mem |awk '{print "Mem="$2"M"}'



参考
1、Getline 
https://www.gnu.org/software/gawk/manual/html_node/Getline_002fVariable_002fPipe.html#Getline_002fVariable_002fPipe