2011-11-07 42 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你是對的,我錯過了。更新答案(與你的答案几乎相同)。 –