一、需求
原始文件A为1.7G的文件,有5列,大约是1700万行的样子。另有2个辅助文件B和C,B、C文件均只有2列。A1和B1相同,A2和C1相同,要提取的数据列为A1、B2、C2、A4、A5,目标文件名为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 接着又出现了新的需求
新的需求是按照A1、B2、C2为分组,对A3、A4、A5分别求和操作。这要是在sql中就可以直接使用groupby 分组来执行了。
参考博客在此:http://linuxguest.blog.51cto.com/195664/424496(awk的类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