Bash

提高使用 grep 進入 while 循環的 Bash 腳本的速度

  • March 9, 2018

讓這個腳本對一個文件工作,這個文件由很多行(> 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 之類的東西重新編寫腳本。使用像這樣的更高級的語言將避免為所有文本處理執行多個程序;您將能夠使用內置函式來做到這一點。

引用自:https://unix.stackexchange.com/questions/426884