假设我们有一个数据文件形如下:
A,B
A,C
A,D
B,E
B,F
D,A
D,B
E,G
....
需求是要将其转变为如下形式:
A:B,C,D
B:E,F
D:A,B
E,G
......
需求很简单,循环遍历文件,然后trace第一列即可。
在这里,我们讨论用Shell脚本如何实现这个简单的需求。
在shell中面对这样的需求,最好的办法莫过于使用awk了,不过除了awk之外,linux也有其他命令能遍历文件内容,比如说cat以及输入重定向等,下面我们就对这几种文件遍历方法做下比较。
首先申明一点,关于文件遍历过程中,如果得到目标结果的逻辑是一样的,说白了就是每读入一行,检查第一列而已。
1. awk方法:
BEGIN{
FS=","
curmember="";
}
{
if(curmember==""){
curmember=$1;
offer=$2;
}
else if(curmember != $1){
print curmember":"offer
curmember=$1;
offer=$2;
}
else{
offer=offer","$2;
}
}
END{
print curmember":"offer;
}
2. forIn+cat方法:
#!/bin/bash
curmember="";
offer="";
#cat orderinfo | while read line
for line in `cat orderinfo`
do
tmpmember=${line%%,*};
if [ "$curmember" == "" ]; then
curmember=$tmpmember
offer=${line##*,}
elif [ "$tmpmember" != "$curmember" ]; then
echo ${curmember}:${offer}
curmember=${tmpmember}
offer=${line##*,}
else
offer=${offer},${line##*,}
fi
done
echo ${curmember}:${offer}
3. 文件描述符打开文件
#!/bin/bash
curmember="";
offer="";
exec 4<orderinfo
while read line<&4
do
tmpmember=${line%%,*};
if [ "$curmember" == "" ]; then
curmember=$tmpmember
offer=${line##*,}
elif [ "$tmpmember" != "$curmember" ]; then
echo ${curmember}:${offer}
curmember=${tmpmember}
offer=${line##*,}
else
offer=${offer},${line##*,}
fi
done
exec 4<&-
echo ${curmember}:${offer}
4. while循环中直接输入重定向
#!/bin/bash
curmember="";
offer="";
while read line
do
tmpmember=${line%%,*};
if [ "$curmember" == "" ]; then
curmember=$tmpmember
offer=${line##*,}
elif [ "$tmpmember" != "$curmember" ]; then
echo ${curmember}:${offer}
curmember=${tmpmember}
offer=${line##*,}
else
offer=${offer},${line##*,}
fi
done<orderinfo
echo ${curmember}:${offer}
四种方法的执行效率如下,文件行数69000+
awk : 185 ms
forIn : 7187 ms
exec : 7931 ms
while : 7708 ms
上述结果中awk速度是最快的,其他三个虽然各有快慢,但都差不多,而且都比awk要慢很多。
这也印证了awk在流式处理文件中的先天优势,同时其代码也是最简单的,屏蔽了文件操作的相关内容。

本文探讨了在Linux环境下,使用Shell脚本处理特定格式数据文件的方法,并对比了awk、forIn+cat、exec、while循环在遍历文件过程中的效率。重点介绍了awk在流式处理文件方面的优势及其实现的简洁性。
1288

被折叠的 条评论
为什么被折叠?



