我有一个小脚本,它只读取文件的每一行,检索id字段,运行实用程序以获取名称并在末尾附加名称。问题是输入文件很大(2GB)。由于输出与附加了10-30个字符名称的输入相同,因此它具有相同的数量级。如何优化它以读取大缓冲区,在缓冲区中处理,然后将缓冲区写入文件,以便最大限度地减少文件访问次数?
#!/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
由于
答案 0 :(得分: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,则无效。)