分类: LINUX
2009-09-22 12:03:25
工作中经常碰上这种情况,需要提取存在于小文件a第1列而不存在于大文件b第1列的数据, 这个可以用awk很快写出代码
awk -F \| '{ if(NR == FNR){userid[$1]=1;} else {if(userid[$1]!=1) print $1;} }' b a
但是,如果文件b(通常情况下b是用户表备份文件)比较大时这个代码就会出现内存溢出的问题了, 这种情况下我们很容易想到,既然b不能全部放在内存,那就倒过来把a放在内存吧,于是会有下面的代码:
awk -F \| '{ if(NR == FNR){userid[$2]=1;} else {if(userid[$1]==1)userid [$1]=0;} } END{for (i in userid){if(userid[i])print i}}' a b
但是,事实证明,这样的代码也不行,因为awk里的数组跟c++的map一样,通过下标访问时就会占存储空间,所以这段代码其实最终也会把b全部存到内存
怎么办呢?方法很多:
1 把b分成两(或更多)部分,依次进行查找
awk -F \| '{ if(NR == FNR){userid[$2]=1;} else if(FNR < 100000) {if(userid[$1]==1)userid[$1]=0;} } END{for (i in userid){if(userid[i])print i}}' a b > c
awk -F \| '{ if(NR == FNR){userid[$2]=1;} else if(FNR >= 100000) {if(userid[$1]==1)userid[$1]=0;} } END{for (i in userid){if(userid[i])print i}}' c b
或者 awk -F \| '{ if(NR == FNR && NR < 10000){userid[$1]=1;} else {if(userid[$1]!=1) print $1;} }' b a > c
awk -F \| '{ if(NR == FNR && NR >= 10000){userid[$1]=1;} else {if(userid[$1]!=1) print $1;} }' b a > c
2 利用awk的in操作符代替if(userid[$1]==1)
awk -F \| '{ if(NR == FNR){userid[$2]=1;} else {if($1 in userid) delete userid[$1];} } END{for (i in userid){if(userid[i])print i}}' b a > d