對於下面的輸入數據,優化AWK腳本對大型數據集
Chr C rsid D A1 A2 ID1_AA ID1_AB ID1_BB ID2_AA ID2_AB ID2_BB ID3_AA ID3_AB ID3_BB ID4_AA ID4_AB ID4_BB ID5_AA ID5_AB ID5_BB
10 p rsid1 q A G 0.00 0.85 0.15 0.70 0.10 0.20 0.40 0.50 0.10 0.30 0.30 0.40 0.10 0.20 0.80
10 p rsid2 q C T 0.90 0.10 0.00 0.80 0.10 0.10 0.70 0.10 0.20 0.30 0.40 0.30 0.30 0.20 0.40
10 p rsid3 q A G 0.40 0.50 0.10 0.80 0.20 0.00 0.20 0.30 0.50 0.50 0.30 0.20 0.20 0.30 0.40
我需要生成以下的輸出數據。
rsid ID1 ID2 ID3 ID4 ID5
rsid1 2.15 1.50 1.70 2.10 2.90
rsid2 1.10 1.30 1.50 2.00 1.90
rsid3 1.70 1.20 2.30 1.70 2.00
表通過用一個常數因子乘以(1, 2, 3)
每ID (ID1, ID2, ID3, etc)
顯示3列(_AA, _AB & _BB)
的總和。
Example: for rsID1 --> ID1 -> (ID1_AA*1 + ID1_AB*2 + ID1_BB*3) = (0.00*1 + 0.85*2 + 0.15*3) = 2.15
我寫了下面的AWK腳本來建立任務,它工作得很好。
請注意:我是AWK的初學者。
awk '{
if(NR <= 1) { # header line
str = $3;
for(i=7; i<=NF; i+=3) {
split($i,s,"_」);
str = str"\t"s[1]
}
print str
} else { # data line
k = 0;
for(i=7; i<=NF; i+=3)
arr[k++] = $i*1 + $(i+1)*2 + $(i+2)*3;
str=$3;
for(i=0; i<=(NF-6)/3; i++)
str = str"\t"arr[i];
print str
}
}' input.txt > out.txt
後來有人告訴我,輸入數據可以是一樣大的60萬行& 300千列,這意味着輸出數據將是60Mx100K。如果我沒有錯,AWK每次只讀一行&,因此一瞬間內存中會有30萬列數據。這是個問題嗎?鑑於這種情況,我該如何改進我的代碼?
有可能進行一些細微的變化,但目前還不能確定,他們將不得不對性能有顯著的影響。其他的調整,比如從每個分支中分解出公用代碼,並且使用慣用的'condition {action}'而不是'if' /'else',與風格相比,更多地與其他任何東西相關。我猜如果你的腳本能夠工作的話,這會更多地進入[codereview.se]的範圍。 –
感謝您的意見@TomFenech,我會更新我的腳本。只是一個簡單的問題,我的一個同事指出我使用'by reference by reference'在'bash'中重寫腳本。我真的不明白這一點。有什麼建議麼? – DhiwaTdG
我不知道_call by reference_的概念如何應用於這種情況,但是在bash中處理文本文件,特別是大文本文件幾乎肯定不是*要走的路。 –