减少while循环的Unix脚本执行时间



有一个引用文件"names.txt";数据如下:

Tom
Jerry
Mickey

注意:文件"中有20k行;names.txt">

还有另一个分隔文件,引用文件中的每个键都有多行"names.txt";如下所示:

Name~~Id~~Marks~~Column4~~Column5

注意:分隔文件中大约有30列:
分隔文件看起来像:

Tom~~123~~50~~C4~~C5
Tom~~111~~45~~C4~~C5
Tom~~321~~33~~C4~~C5
.
.
Jerry~~222~~13~~C4~~C5
Jerry~~888~~98~~C4~~C5
.
.

需要为文件"names.txt"中"Marks"列中具有最高值的每个键从分隔文件中提取行
因此,输出文件中的每个键都会有一行,即文件"names.txt"。

下面是我在unix中截取的代码,它运行得很好,但执行脚本大约需要2个小时

while read -r line; do
getData `echo ${line// /}`
done < names.txt
function getData
{
name=$1
grep ${name} ${delimited_file} | awk -F"~~" '{if($1==name1 && $3>max){op=$0; max=$3}}END{print op} ' max=0 name1=${name} >> output.txt
}

有没有什么方法可以并行化并减少执行时间。只能使用shell脚本

优化bash脚本的经验法则:
输入的大小不应影响程序的运行频率

您的脚本很慢,因为bash必须运行函数20k次,这涉及到启动grepawk。仅仅启动程序就需要大量的时间。因此,尝试一种程序启动次数不变的方法。

这里有一种方法:

  1. 处理第二个文件,这样对于每个名称,只保留带有最大标记的行
    可以用sortawk,或者sortuniq -f+Schwartzian变换来完成
  2. 然后只保留那些名称出现在names.txt中的行
    使用grep -f轻松

sort -t'~' -k1,1 -k5,5nr file2 |
awk -F'~~' '$1!=last{print;last=$1}' |
grep -f <(sed 's/.*/^&~~/' names.txt)

sed部分将名称转换为正则表达式,确保只有第一个字段匹配;假定名称不包含像CCD_ 10和CCD_。

根据第一个文件和第二个文件之间的关系,交换这两个步骤可能会更快。结果是一样的。

最新更新