Shell脚本中利用awk处理大批量数据

一、需求

    原始文件A1.7G的文件,有5列,大约是1700万行的样子。另有2个辅助文件BCBC文件均只有2列。A1B1相同,A2C1相同,要提取的数据列为A1B2C2A4A5,目标文件名为D.txt

二、思路

    2.1在使用awk处理数据之前,考虑使用whileread ……done<A.txt的方式来处理数据,但是执行效率太低,并不符合期望。

    2.2后来使用awk处理数据,但是必须要解决的问题是传入外部数组或者是将三个文件的数据传入到awk中。

 

三、解决方式

3.1 使用while read ……done<A.txt的方式来处理数据

while read B1  B2

         do

         B_array[$B1]=$B2

         done<B.txt

        

while read C1  C2

         do

         C_array[$C1]=$C2

done <B.txt

                  

while read A1 A2 A3 A4 A5

         do

         B2_value=B_array[$A1]

         C2_value=C_array[$A2]

         echo$A1,$B2_value,$C2_value,$A3,$A4,$A5>>D.txt

         fi

done <A.txt

 

#数据量少时可以使用第一种方式。

 

3.2 外部数组传入awk

    awk多文件处理,我遇到一个无法解决的问题,就是将3个文件读入到awk中就直接打印了,不可能执行其他的操作,于是我就放弃了这种方式而改用将外部数组传入到awk中的方式。于是我找到了以下代码

awk -vs1="${time[*]}" -v s2="${!time[*]}" '

BEGIN{split(s1,s3,"");split(s2,s4," ");

for(i=1;i<=length(s4);i++)

res[s4[i]]=s3[i];}'

(参考博客:http://sunlujing.iteye.com/blog/1918907

 

最终处理数据的代码就变成了如下方式:

while readB1  B2

         do

         B_array[$B1]=$B2

         done <B.txt

        

while readC1  C2

         do

         C_array[$C1]=$C2

done <B.txt

                  

awk -F",", -v s1="${B_array[*]}" -v s2="${!B_array[*]}"-v w1="${C_array[*]}" -v w2="${!C_array[*]}" '

BEGIN{

split(s1,s3,",");

split(s2,s4,",");

for(i=1;i<=length(s4);i++)

B_new_array[s4[i]]=s3[i];

 

split(w1,w3,",");

split(w2,w4,",");

for(i=1;i<=length(w4);i++)

C_new_array[w4[i]]=w3[i];

}

{

len=split($1,A_array,"")

A1=A_array[1];

A2=A_array[2];

A3=A_array[3];

A4=A_array[4];

A5=A_array[5];

 

B2_value=B_new_array[A1];

C2_value=C_new_array[A2];

 

printA1,B2_value,C2_value,A3,A4,A5

 

}' A.txt>>D.txt

#执行时间大约是4分钟。

3.3 接着又出现了新的需求

新的需求是按照A1B2C2为分组,对A3A4A5分别求和操作。这要是在sql中就可以直接使用groupby 分组来执行了。

参考博客在此:http://linuxguest.blog.51cto.com/195664/424496awk的类sql数据处理

然后代码就变成了下面这样:

while readB1  B2

         do

         B_array[$B1]=$B2

         done <B.txt

        

while readC1  C2

         do

         C_array[$C1]=$C2

done <B.txt

                  

awk -F",", -v s1="${B_array[*]}" -v s2="${!B_array[*]}"-v w1="${C_array[*]}" -v w2="${!C_array[*]}" '

BEGIN{

split(s1,s3,",");

split(s2,s4,",");

for(i=1;i<=length(s4);i++)

B_new_array[s4[i]]=s3[i];

 

split(w1,w3,",");

split(w2,w4,",");

for(i=1;i<=length(w4);i++)

C_new_array[w4[i]]=w3[i];

}

{

len=split($1,A_array,"")

A1=A_array[1];

A2=A_array[2];

A3=A_array[3];

A4=A_array[4];

A5=A_array[5];

 

B2_value=B_new_array[A1];

C2_value=C_new_array[A2];

 

A3_array[A1","B2_value","C2_value]+=A3;

A4_array[A1","B2_value","C2_value]+=A4;

A5_array[A1","B2_value","C2_value]+=A5;}

 

END{

for( i inA3_array)

{       

         printi","A3_array[i]","A4_array","A5_array

 

}

}' A.txt>>E.txt


你可能感兴趣的:(shell脚本,awk处理数据,awk类sql操作)