linux 执行效率,awk[执行效率]的问题

博客讲述了在处理大量数据时,如何通过优化awk命令提高效率。原始方法使用for循环进行逐行比较,导致处理时间过长。经过优化,使用`if($2 in a)`的判断方式,大幅减少了执行时间。优化后的命令避免了重复遍历,提升了搜索速度。同时,文中还介绍了awk的`next`函数,用于跳过不满足条件的记录。
摘要由CSDN通过智能技术生成

背景:

甲方客户有个需求,有三个文件,要我拿两个文件与另个文件对比,把重复的找出来。

首先我应该:

-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$

扯淡:

快春节了,最近忙的跟狗一样,还有好多事情没搞定,今天来这写了篇博客,是不是有点扯淡。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值