2010-12-13 114 views
1

我有一个小脚本,只读取文件的每一行,检索id字段,运行实用程序获取名称并在末尾附加名称。问题是输入文件很大(2GB)。由于输出与添加了10-30个char名称的输入相同,因此它具有相同的数量级。我怎样才能优化它来读取大型缓冲区,在缓冲区中进行处理,然后将缓冲区写入文件,从而使文件访问次数最小化?ksh脚本优化

#!/bin/ksh 
while read line 
do 
    id=`echo ${line}|cut -d',' -f 3` 

    NAME=$(id2name ${id} | cut -d':' -f 4) 

    if [[ $? -ne 0 ]]; then 
     NAME="ERROR" 
     echo "Error getting name from id2name for id: ${id}" 
    fi 

    echo "${line},\"${NAME}\"" >> ${MYFILE} 
done < ${MYFILE}.csv 

感谢

回答

1

您可以通过消除在每次循环的两次调用cut大大加快速度。将重定向移动到输出文件到循环结束可能会更快。既然你不显示输入行的例子,或者什么id2name由(它可能是一个瓶颈),或者什么它输出的样子,我只能提供这种近似:

#!/bin/ksh 
while IFS=, read -r field1 field2 id remainder # use appropriate var names 
do 
    line=$field1,$field2,$id,$remainder 
    # warning - reused variables 
    IFS=: read -r field1 field2 field3 NAME remainder <<< $(id2name "$id") 
    if [[ $? -ne 0 ]]; then 
     NAME="ERROR" 
     # if you want this message to go to stderr instead of being included in the output file include the >&2 as I've done here 
     echo "Error getting name from id2name for id: ${id}" >&2 
    fi 
    echo "${line},\"${NAME}\"" 
done < "${MYFILE}.csv" > "${MYFILE}" 

操作系统会做为你缓冲。

编辑:

如果你的KSH的版本没有<<<,试试这个:

id2name "$id" | IFS=: read -r field1 field2 field3 NAME remainder 

(如果你使用bash,这是行不通的)

+0

谢谢丹尼斯。 id2name根据id获取用户名,我无法控制该实用程序。但是,我希望拥有ID和相应的名称,并在击中数据库之前执行本地查找。我尝试排版-A,但它不被ksh识别。不幸的是,在SunOS上,ksh93不可用。有其他解决方案吗?谢谢 – Kiran 2010-12-13 19:54:05

+0

嗯,得到这条线的语法错误:IFS =:读-r field1 field2 field3 NAME其余<<< $(id2name $ id) 语法错误在第9行:'<'意外 它是<<而不是<<<或者是我的解释器不好的版本? – Kiran 2010-12-13 20:01:12

+0

@Kiran:看到我编辑的答案。 – 2010-12-13 21:11:25