用awk实现求和、均值、最值操作


没事的时候喜欢在网上逛,所以专门注册了个号订阅了大量感兴趣的RSS,今早在逛的时候发现了个感兴趣的title“Awk求最大值正解”,然后就点进去看,在验证的过程中确实学到了点东西。

最先开始看到标题的时候想了想用awk该怎么实现,思路的话类似于做一次冒泡排序(感觉和简单选择排序也很像?求指点。)(冒泡排序就是把小的元素往前调或者把大的元素往后调,比较是相邻的两个元素比较,交换也发生在这两个元素之间。)但这里的话不用进行元素的交换,因为只需要获取最大/小值,所以只需要比较即可,设置一个临时变量max/min初值为0,然后从第一行开始进行比较,若max/min比它大/小,则将max/min修改为该值的大小,当进行了NR次比较之后即可获取该列的最值。

思路大概就是这样,不过我还是先去网上找的代码(不知道这到底是个好习惯还是坏习惯,自己从头开始实现的话可以锻炼自己的思维能力和调试能力,而且印象会比较深刻,不过就是“浪费时间”,因为很多时候这种问题在网上是能够找到现成的解决方案的,并且别人的思路/实现会比你自己想出来的要高效。多参考别人的代码/思路在前期是个不错的提高方式,但到了后期,还是得自己想方设法去实现,否则能力这方面永远还是提不上来,得学会创造!)

打开搜索引擎(Google被封了之后我一般用Bing,有时用Baidu、AOL、Yahoo、duckduckgo,实在找不到了才去Google),输入关键字“awk 求列的最大值”,点开几个链接,大致甄别了一下,选出几个:

其中的第一个里面就直接包含了“求和、平均、最大值和最小值”的计算操作,先不多说,实际测试一下:

# cat calc
490898
1189235
20212
1494270
146515
29369
23563
563027
22976
127809
16813
551646
18858
18977

# cat calc | awk 'BEGIN{max=0} {if(($1+0)>max) max=($1+0) fi} END{print "Max = ",max}'
Max = 563027
# cat calc | awk 'BEGIN{max=0} {if(($1+0)>(max+0)) max=$1 fi} END{print "Max = ",max}'
Max = 1494270

因为默认情况下,awk 是按字符串方式进行比较的,但我们这里是想让其按照数字的方式进行比较,所以为了能正确获取到最大值,需要让awk按数字的方式去比较,在比较前需要先将变量强制转换为整数型,这样获取到的最大值才会是正确的。

awk ‘BEGIN {max = 0} {if ($1+0 > max+0) max=$1 fi} END {print “Max=”, max}’ data

这里可以看到在比较前对两个变量先加0(两个变量需要同时做转换,不然也得不到预期效果),就相当于是做从字符串到数字类型的转换操作。只有在比较操作的时候需要进行转换,如果只是求和的话就不用了。下面放上这几种操作的命令组合:

#1、求和
cat data | awk '{sum+=$1} END {print "Sum = ", sum}'

#2、求平均
cat data | awk '{sum+=$1} END {print "Average = ", sum/NR}'

#3、求最大值
cat data|awk 'BEGIN{max=0} {if ($1+0 > max+0) max=$1 fi} END{print "Max=", max}'

#4、求最小值(min的初始值设置一个超大数即可)
awk 'BEGIN{min = 1999999} {if ($1+0 < min+0) min=$1 fi} END{print "Min=", min}'

#5、求访问次数的Top 10 Resource,可以根据此进行优化
cat output/logs/cookie_logs/`date +%u`/cookie_log | grep -v '172.16' | grep -v '127.0.0.1' | awk -F' ' '{ if(index($1,"219.141.246")!=0) print $2; else print $1 }' | sort | uniq -c | sort -n | tail -10

 

参考链接:

如何将从网页中复制的内容输出/复制到Linux下的文件中?

这里有几个知识点:重定向Here Document
实例如下:
# cat >calc <<EOF
> 490898
> 1189235
> 20212
> 1494270
> 146515
> 29369
> 23563
> 563027
> 22976
> 127809
> 16813
> 551646
> 18858
> 18977
> EOF

# cat calc
490898
1189235
20212
1494270
146515
29369
23563
563027
22976
127809
16813
551646
18858
18977

参考链接:

http://blog.sina.com.cn/s/blog_73aca59701010pcs.html

, ,

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注