2011-11-07 86 views
3

我有这个脚本运行在一个1.7GB的文本文件中。ShellScript:grep + while + cut + awk在一个大文件中=很慢

#!/bin/bash 

File1=$1.tmp 
File2=$1.modified 

grep '^#' $1 > $File2 
grep -v '#' $1 > $File1 

while read line; do 
     column_four=$(echo $line | cut -d " " -f4) 
     final_line=$(echo $line | cut -d " " -f4-5) 
     if [ "$column_four" == "0" ]; then 
       beginning_line=$(echo $line | cut -d " " -f1-3) 
       final_line=$(echo $line | cut -d " " -f4-5) 
     else 
       final_line=$(echo $line | cut -d " " -f1-2) 
     fi 
     linef=$(echo "$beginning_line $final_line") 
     echo $linef | awk '{printf "%5.0f%12.4f%12.4f%5.0f%12.4f\n", $1, $2, $3, $4, $5}' >> $File2 
done < $File1 
rm -f $File1 

问题:它非常非常慢。它使用Core2Duo创建一个新文件,其列以每分钟200KB的速度排列。我怎样才能让它更快?

谢谢。

+0

请发表您的输入文件,例如预期/所需输出的样本。 –

回答

3

我会与环废除并使用awk的一次调用:

awk ' 
{ 
    if ($4 == 0) { 
     f1 = $1; 
     f2 = $2; 
     f3 = $3; 
     f4 = $4; 
     f5 = $5; 
    } else { 
     f4 = $1; 
     f5 = $2; 
    } 
    printf ("%5.0f%12.4f%12.4f%5.0f%12.4f\n", f1, f2, f3, f4, f5); 
}' < $File1 >> $File2 

你不调用awkecho和每个输入文件的行cut多次,只是运行这样一个单独的awk过程。

+0

你忘了过滤出以'#'开头的行,但这将是微不足道的。 –

+0

@JanHudec:该行只是作为while循环的替代品,但我的回答并不明确。 – beny23

+0

但它也可以代替grep。在可以处理它的'{}'块之前可以有一个正则表达式。 –

3

可以在awk整个事情,据我看到的,像

awk '/^#/ { print $0 >> "File2" ; getline} 
    $0 ! ~ /#/ { if ($4 == 0) { 
        f1 = $1 ; f2 = $2 ; f3 = $3 
        printf("%5.0f%12.4f%12.4f%5.0f%12.4f\n", f1, f2, f3, $4, $5) >> "File2" } 
        else { printf("%5.0f%12.4f%12.4f%5.0f%12.4f\n", f1, f2, f3, $1, $2) >> "File2" } 
         } INPUTFILE 
+1

不要认为这在功能上是等价的,因为如果第4列是“0”,shell代码只会重置'$ beginning_line'变量,否则重新使用这些值。 – beny23

+0

@ beny23你是对的,我错过了。更新答案(与你的答案几乎相同)。 –