Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1647277
  • 博文数量: 409
  • 博客积分: 6240
  • 博客等级: 准将
  • 技术积分: 4908
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-01 00:04
文章分类

全部博文(409)

文章存档

2021年(1)

2019年(1)

2017年(1)

2016年(13)

2015年(22)

2013年(4)

2012年(240)

2011年(127)

分类: Python/Ruby

2011-12-27 16:25:16

背景:

甲方客户有个需求,有三个文件,要我拿两个文件与另个文件对比,把重复的找出来。
首先我应该:
-bash-3.2$ sort 12.12-12.19.txt |awk '{print $1}' |uniq -d
-bash-3.2$ sort 12.19-12.26.txt |awk '{print $1}' |uniq -d
-bash-3.2$ sort xinmin.txt |awk '{print $1}' |uniq -d |sed "s/\(.*\)....$/\1/g"
-bash-3.2$ cat xu001.txt  |sed "s/\(.*\)....$/\1/g"
ad48475
ad48495
ad48523
ad48527
ad48559
ad48610
ad509ad50328
//涉及用户信息,删掉几位。

结果:

我将要对比的基准文件里面有重复,而拿来对比的两个文件里面没有重复,那就是他要的结果就是没有用户ad了。
过程:

现在我有两个文件,file1( 12.12-12.19.txt ),file2,现在要找出来file里面的第一列是否存在file2中的第二列,如果有的话就print。
-bash-3.2$ head 12.12-12.19.txt 
ad486327      281830  7.041G  287.466M        6.754G

-bash-3.2$ head xinmin.txt 
AD00000989    ad485478

-bash-3.2$ 
其中file1 一万多行,file2 十二万行,数据量是非常大的。
-bash-3.2$ awk 'NR==FNR{a[FNR]=$1;b=FNR}NR>FNR{for(i=1;i<=b;i++)if(a[i]==$2)print a[i]}'  file2 file1
执行了将近一个小时。。。
后来在群里问别人,群主无名(awk天王)出现,指出我那个for循环的地方效率比较低,给我优化了一下:
-bash-3.2$ awk 'NR==FNR{a[¥1];next}NR>FNR{if($2 in a)print $0}' file1 file2

//-bash-3.2$ awk 'NR==FNR{a[FNR]=$1;b=FNR}NR>FNR{for(i in a)if($2==a[i])print a[i]}' 12.12-12.19.txt xinmin.txt  这样也可以。
结果10几秒钟就可以输出结果了!!!我震惊了!!!

感悟:

我的方法使用for循环一个一个对比的,处理几百对1万的数据量,还是可以的,但是1万多对10几万,就悲剧了。无名的方法是先讲file的$1赋值给数组a,if($2 in a)这一个判断$2是否是数组里面(数组的元素)。
提问:

为什么第二种效率会那么高?时间复杂度上我觉得也是一样的啊?
猜想:
我的执行顺序是先读入数组a,然后读入file2的时候,反复循环a里面的数据,如果符合条件,就打印。他的顺序是输入数组a,然后在读入file2的时候,判断file2的$2是否在a中,这样应该也是一个一个对比的。只是我对比的是数组里面的元素,他对比的数组的分量。也许是awk语法或者其处理规则问题,对于if($2 in a)这种方式,就快一点儿。

for(i in a)if($2==i)要比for(i=1;i<=FNR;i++)if(a[i]==$2)高效的多。for (i in a) 是可以的,for ($1 in a) 不对,if (i in a )、if($1 in a )都可以的。

备注:

那个地方不能用for(¥2 in a),因为for(i in a)是固定格式。for(i in a)是将a中所有的元素(输出、运算)。如果file1 file2里面有不同的重复情况,上面的两个执行结果就不同了。
看下面:
file2 有18行是一样的, file3 29行市一样的。
-bash-3.2$ echo $((522/18))
29
-bash-3.2$ awk 'NR==FNR{a[$1];next}NR>FNR{if($1 in a)print $0}' file2 file3
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
ad48956231
-bash-3.2$ awk 'NR==FNR{a[$1];next}NR>FNR{if($1 in a)print $0}' file2 file3 | wc -l
29
-bash-3.2$  awk 'NR==FNR{a[FNR]=$1;b=FNR}NR>FNR{for(i=1;i<=b;i++)if(a[i]==$1)print a[i]}' file2 file3 |wc -l
522
-bash-3.2$ 
-bash-3.2$ awk 'NR==FNR{a[$1]=$1}NR>FNR{if(!($1 in a)){print $1}}' file2 file3
-bash-3.2$ awk 'NR==FNR{a[$1]=$1}NR>FNR{if(!($1 in a)){print $1}}' file3 file2
ad4855778
ad48569767
ad50002080
ad4851433
ad50003290
ad5000144
ad50001413
ad4863582
-bash-3.2$ 
-bash-3.2$ awk 'NR==FNR{a[$0]=1}NR>FNR{if!((a[$0]))print}' file3 file2
awk: NR==FNR{a[$0]=1}NR>FNR{if!((a[$0]))print}
awk:                          ^ syntax error
awk: NR==FNR{a[$0]=1}NR>FNR{if!((a[$0]))print}
awk:                                    ^ syntax error
-bash-3.2$ awk 'NR==FNR{a[$0]=1}NR>FNR{if(!(a[$0]))print}' file3 file2
ad4855778
ad48569767
ad50002080
ad4851433
ad50003290
ad5000144
ad50001413
ad4863582
-bash-3.2$ 
#############################################分割#############################################
-bash-3.2$ awk 'NR==FNR{a[$1];next}NR>FNR{if($2 in a)print $0}' file1 xinmin.txt 
ʺAD00000027   ad489531
AD00000029    ad48557478
AD00000098    ad489767
AD00003110    ad502080
AD008    ad4133
AD000344    ad003290
AD0000357    ad500054
AD0000361    ad500413
AD00006   ad486821
-bash-3.2$ awk 'NR==FNR{a[$1];next}NR>FNR{for($2 in a)print $0}' file1 xinmin.txt 
awk: NR==FNR{a[$1];next}NR>FNR{for($2 in a)print $0}
awk:                                      ^ syntax error
-bash-3.2$ awk 'NR==FNR{a[$1];next}NR>FNR{for(i in a)if($2==i)print $0}' file1 xinmin.txt 
ʺAD00000027   ad489531
AD00000029    ad48557478
AD00000098    ad489767
AD00003110    ad502080
AD008    ad4133
AD000344    ad003290
AD0000357    ad500054
AD0000361    ad500413
AD00006   ad486821
-bash-3.2$ 
#############################################分割#############################################
对于他用到了next,其实我不会用这个函数,就百度了下:
next停止对当前输入记录的处理,从下一个输入记录继续。!!!
比如:
-bash-3.2$ cat heige.txt 

2  b
3  c
4  d
5  e
6  f
7  g
8  h
9  i
10 j
fa  fal
lew 3
-bash-3.2$  awk '$0~/f/{next}{print}'

-bash-3.2$  awk '$0~/f/{next}{print}' heige.txt 

2  b
3  c
4  d
5  e
7  g
8  h
9  i
10 j
lew 3
-bash-3.2$ 

扯淡:

快春节了,最近忙的跟狗一样,还有好多事情没搞定,今天来这写了篇博客,是不是有点扯淡。。。
阅读(2236) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~