2013-01-08 14 views
1

我想在Unix中截斷TSV文件的第4列給定的長度。文件的記錄數以百萬計,大小爲8GB。有什麼更快的方法來截斷Unix中的列

我想這個,但它似乎有點慢。

awk -F"\t" '{s=substr($4,0,256); print $1"\t"$2"\t"$3"\t"s"\t"$5"\t"$6"\t"$7}' file > newFile 

是否有更快的替代方案?

感謝

+1

它現在有多快?你想要多快?沒有數字,你不能有意義地談論性能。 –

回答

2

你的命令可以寫得很好多一點(假設你重新建立記錄),這可能會給一些性能的提高:

awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,256) }' file > newFile 

如果你有機會到多核心機器(你可能會這樣做),你可以使用GNU parallel。你可能想改變你使用(我已經設置4在這裏)的核心數量和美聯儲對awk(我已經將其設置爲兩兆)的塊大小...

< file parallel -j 4 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' > newFile 


這裏的一些測試中,我用100萬線2.7G文件和2M的塊大小在我的系統上:

time awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' file >/dev/null 

結果:

real 1m59.313s 
user 1m57.120s 
sys  0m2.190s 

隨着一個核心:

time < file parallel -j 1 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' >/dev/null 

結果:

real 2m28.270s 
user 4m3.070s 
sys  0m41.560s 

四個核:

time < file parallel -j 4 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' >/dev/null 

結果:

real 0m54.329s 
user 2m41.550s 
sys  0m31.460s 

有十二核心:

time < file parallel -j 12 --pipe --block 2M -q awk 'BEGIN { FS=OFS="\t" } { $4 = substr($4,0,2) }' >/dev/null 

結果:

real 0m36.581s 
user 2m24.370s 
sys  0m32.230s 
+1

非常感謝在研究中的這些努力。我不是故意要比較所有方法在幾秒鐘內的表現。我問這個問題只是爲了確保我的方法不是非常低效。 – RandomQuestion

2

我會假設你的文件有領域和在該行的開頭沒有空格之間只有一個空格字符。如果這是錯誤的,這可以被增強。 否則,這應該工作:

sed 's/^\([^ ]* [^ ]* [^ ]* [^ ]\{1,256\}\)[^ ]* /\1 /' 

我還沒有實際使用256個字符長的數據來測試它(我\{1,2\}測試它,我不知道如何它的速度比較到的awk BTW,在一些版本中,你可能需要從花括號離開過反斜線和只使用{1,256}

2

如果斯科特或史蒂夫的解決方案仍然太慢,它可能是時間打出來的C.運行方式./a.out <file> newFile。測試首先在一個長字段的小文件上;我不是100%肯定我有數學權利。

#include <stdio.h> 
int 
main(void) 
{ 
    int field = 1; 
    int character = 0; 
    int c; 
    while ((c = getchar()) != EOF) 
    { 
     switch (c) 
     { 
     case '\n': 
      field = 1; 
      character = 0; 
      break; 
     case '\t': 
      character = 0; 
      field++; 
      break; 
     default: 
      character++; 
      break; 
     } 
     if (field != 4 || character < 256) 
      putchar(c); 
    } 
    if (ferror(stdout) || fflush(stdout) || fclose(stdout)) 
    { 
     perror("write"); 
     return 1; 
    } 
    return 0; 
} 
相關問題