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

Reduce Unix Script execution time for while loop

有一个参考文件“names.txt”,其数据如下:

Tom
Jerry
Mickey

注意:文件“names.txt”中有20k行

参考文件“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=
   grep ${name} ${delimited_file} | awk -F"~~" '{if(==name1 && >max){op=[=13=]; max=}}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'~~' '!=last{print;last=}' |
grep -f <(sed 's/.*/^&~~/' names.txt)

sed 部分将名称转换为正则表达式,以确保仅匹配第一个字段;假设名称不包含特殊符号,如 .*.

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