Bash
提高使用 grep 進入 while 循環的 Bash 腳本的速度
讓這個腳本對一個文件工作,這個文件由很多行(> 500Mb)組成:
odd lines: >BLA_BLA lenght_XX cov.XX even lines: AGCAGCAGACTCAGACTACAGAT # on even lines there's a DNA sequence
它的功能是在“cov”之後重新計算值。使用參數傳遞的參數並替換舊的參數併計算“G”和“C”進入 DNA seq 的百分比,以偶數行為單位。
所以,輸出看起來像:
> BLA_BLA lenght_XX > nucleotidic_cov XX > DNA seq (the same of even lines) > GC_CONT: XX
這是程式碼(只有循環):
K=$(($READLENGHT - $KMER + 1)) Y=$(echo "scale=4; $K / $READLENGHT" | bc) while read odd; do echo -n "${odd##}" | cut -d "_" -f 1,2,3,4 && printf "nucleotide_cov: " echo "scale=4;${odd##*_} / $Y" | bc read even echo "${even##}" && ACOUNT=$(echo "${even##}" | sed -e "s/./&\n /g" | grep -c "A") GCOUNT=$(echo "${even##}" | sed -e "s/./&\n /g" | grep -c "G") CCOUNT=$(echo "${even##}" | sed -e "s/./&\n /g" | grep -c "C") TCOUNT=$(echo "${even##}" | sed -e "s/./&\n /g" | grep -c "T") TOTALBASES=$(($ACOUNT+$GCOUNT+$CCOUNT+$TCOUNT)) GCCONT=$(($GCOUNT+$CCOUNT)) printf "GC_CONT: " echo "scale=2;$GCCONT / $TOTALBASES *100" | bc done < "$1"
在 16 核伺服器上執行巨大的文本文件(大於 500Mb)時速度非常慢。關於如何提高這個腳本的速度的任何想法?
編輯
根據要求,通過 pastebin 提供所需的 I/O:https ://pastebin.com/FY0Z7kUW
百分比計算可以簡化為這樣的單個操作
echo "${even##}" | awk '{x=gsub(/[ACT]/,""); y=gsub(/G/,""); printf "GC_CONT : %.2f%%\b", (y*100)/(x+y) }'
gsub 替換一個模式並返回它所做的替換計數。這樣就可以用來快速計算百分比。
您還可以在 awk 中處理奇數行和偶數行。目前尚不清楚你在用奇數行做什麼,但你的完整功能可以放在一個 awk 中 -
awk -F '_' -v Y="$Y" '{ if(NR%2==1) { printf "%s %s %s %s %s\nnucleotidic_cov : %.4f\n",$1,$2,$3,$4,$5, ($6 / Y) } else { x=gsub(/[AT]/,""); y=gsub(/[GC]/,""); printf "GC_CONT : %.2f%%\n", (y*100)/(x+y) } }' large_file
編輯:根據 OP 的要求,更改了奇數行的 if 塊。gsub 將刪除“cov”。從號碼。將 shell 變數 $Y 傳遞給 awk 後,我們現在可以按所需格式進行分割和列印。
使用單個 awk 腳本而不是多個操作將顯著加快操作速度。
您已經達到(委婉地說)可以在 shell 中合理完成的限制——您應該用 AWK、Perl 或 Python 之類的東西重新編寫腳本。使用像這樣的更高級的語言將避免為所有文本處理執行多個程序;您將能夠使用內置函式來做到這一點。