​追梦人博客Dream.ren

追梦人 Dream.ren

Linux下几种去重方法的比较

博客又双叒叕一个多月没更了,今天(好吧,我承认这是之前的存稿)就来比较下Linux下对数据去重处理的几种方式,更具体一点讲就是比较sort -u、uniq、awk '!x[$0]++' 等方法的效果与效率。

输入文件为Nginx的日志文件,共100万行,文件名为nginx.log,其格式为“时间|用户IP|主机名|发送流量(字节)|下载流量(字节)|耗时(毫秒)”
具体内容截取如下(部分内容已被隐藏):

2018-03-03T20:00:52+08:00 | 116.237.***.205 | *****.********.com | 780 | 4319 | 1.495
2018-03-03T20:00:52+08:00 | 39.181.***.45 | *****.********.com | 3820 | 3777 | 1.480
2018-03-03T20:00:52+08:00 | 101.87.***.203 | *****.********.com | 617 | 4427 | 29.249
2018-03-03T20:00:52+08:00 | 183.206.***.72 | *****.********.com | 2481 | 5164 | 20.894
2018-03-03T20:00:52+08:00 | 59.56.***.98 | *****.********.com | 825 | 4425 | 1.679
2018-03-03T20:00:53+08:00 | 27.198.***.59 | www.******.**.** | 287 | 1034 | 240.426
2018-03-03T20:00:53+08:00 | 112.67.***.155 | *****.********.com | 2914 | 726 | 40.238
2018-03-03T20:00:53+08:00 | 153.34.***.97 | *****.********.com | 552 | 4420 | 185.736
2018-03-03T20:00:53+08:00 | 113.232.***.0 | www.******.com | 124 | 3221 | 1.022

接下来分别采用上面几种不同的方式去重提取出用户IP地址并比较其效率,每种方法各执行三次取消耗时间的平均值。

第一种方式:sort+uniq:

提到文本去重,Linux下有个uniq工具,顾名思义就是用来取唯一值的嘛!uniq走起!但,但是,,,uniq命令只能对相邻的重复行去重,所以在使用uniq前需要先排序,使相同内容的行相邻,再去重才行,于是就有了下面的命令:

time awk 'BEGIN{FS="|"}{print $2}' nginx.log|sort|uniq >/dev/null

耗时:0m7.609s、0m7.538s、0m7.782s 平均:7.643s
注意:这种去重方式会改变待处理内容原本的行序!

第二种方式:sort -u:

uniq使用前还得保证相同行相邻,是不是觉得很鸡肋?sort命令其实是有取唯一值功能的,只需加个-u参数即可:

time awk 'BEGIN{FS="|"}{print $2}' nginx.log|sort -u >/dev/null

耗时:0m6.242s、 0m6.136s、0m5.920s 平均:6.099s
可以看到直接使用sort -u比sort后再uniq要节省一点时间!这种方式同样也是会改变原本的行序的。

第三种方式:awk:

哇!重量级工具出场了!awk是一个非常强大的文本分析处理工具,用起来非常爽!awk支持关联数组,下面三条命令原理和效果基本是一样的,都是把IP作为key进行处理,区别是前两条是直接把第一次出现的IP输出出来,非第一次出现的IP直接忽略;第三条是,遍历所有行后直接输出key实现去重操作。

time awk 'BEGIN{FS="|"}{print $2}' nginx.log|awk '!x[$0]++' >/dev/null
time awk 'BEGIN{FS="|"}{if(!x[$2]++){print $2}}' nginx.log >/dev/null
time awk 'BEGIN{FS="|"}{a[$2]}END{for(i in a)print i }' nginx.log >/dev/null

耗时:
第一条:0m2.362s、0m2.405s、0m2.052s 平均:2.273s
第二条:0m2.116s、0m2.130s、0m2.151s 平均:2.132s
第三条:0m2.238s、0m1.944s、0m2.251s 平均:2.144s
这种利用awk关联数组的去重方式无需进行耗时的排序操作,也就没有那么高的时间复杂度,当处理的内容较多时,效率优势就非常明显了,而且前两条命令是不会改变原内容出现先后顺序的,各行出现的顺序还是原来的!可以说是非常完美的一种去重方式了!

总结:当待去重的数据量非常大或者有保留原有行序需求的时候,应该选择使用awk对数据进行去重!其他情况下嘛!看心情随便选一个就行~~~

评论回复

  1. 回复 visij

    啊啊啊啊啊啊啊啊

  2. 回复 保密

    博主Pixiv是不支持了吗

3 + 5 =

回到顶部