重击而非常慢

时间:2018-11-19 08:51:49

标签: linux bash performance shell while-loop

我有一个while循环,该循环读取邮件日志文件并将其放入数组中,因此我将能够在数组中搜索并匹配/搜索流。不幸的是,while循环需要很长时间才能遍历文件,这是一个非常大的文件,但是必须有另一种更快的方式来完成此操作。

cat /home/maillog |grep "Nov 13" |grep "from=<xxxx@xxxx.com>" |awk '{print $6}' > /home/output_1 

while read line; do awk -v line="$line" '$6 ~ line { print $0 }' /home/maillog >> /home/output_2 ; done < /home/output_1

有什么想法吗?谢谢你。

1 个答案:

答案 0 :(得分:4)

让我们分析您的脚本并尝试解释为什么它很慢。

让我们首先从对第一行进行微优化开始。不会加快速度,但这仅仅是教育性的。

cat /home/maillog |grep "Nov 13" |grep "from=<xxxx@xxxx.com>" |awk '{print $6}' > /home/output_1 

在这一行中,您对不同的二进制文件进行了4次调用,最后可以一次调用一次。为了提高可读性,您可以保留此行。但是,这里有两个要点:

  1. cat的无用用法。程序cat主要用于合并文件。如果仅添加一个文件,则基本上是多余的。尤其是如果您要将其传递给grep

    cat file | grep ... => grep ... file
    
  2. 与awk结合使用的多个抓握...可以写为单个awk

    awk '/Nov 13/ && /from=<xxxx@xxxx.com>/ {print $6}'
    

因此整行可以写为:

awk '/Nov 13/ && /from=<xxxx@xxxx.com>/ {print $6}' /home/maillog > /home/output_1

第二部分是事情变慢的地方:

while read line; do 
   awk -v line="$line" '$6 ~ line { print $0 }' /home/maillog >> /home/output_2 ;
done < /home/output_1

为什么这么慢?您从/home/output_1表格中读取的每一行,都将程序awk加载到内存中,打开文件/home/maillog,对其进行处理,然后关闭文件/home/maillog。同时,在处理的每一行中,每次打开/home/output_2,将文件指针置于文件末尾,写入文件,然后再次关闭文件。

整个程序实际上可以通过一个awk完成:

awk '(NR==FNR) && /Nov 13/ && /from=<xxxx@xxxx.com>/ {a[$6];next}($6 in a)' /home/maillog /home/maillog > /home/output2