web-dev-qa-db-ja.com

grepを使用して1回のパスで複数のパターンをカウントしますか?

DNA配列を含むgzip圧縮されたDNAfastaファイル内のDNAトリヌクレオチドを繰り返しカウントするgrepループを作成しました。

declare -a tri=(AAA AAC AAG AAT CAA .. etc)

for i in ${tri[@]}
do
   gzip -cd gencode.v18.pc_transcripts.fa.gz | grep -v "^>" | grep -o $i | wc -l
done

Fastaファイルがこの形式である場合(はるかに大きいですが)

head test.fa
>id1
TTTTTAAAAA
>id2
GGGGGCCCCC
etc..

これは機能しますが(つまり、各トリヌクレオチドの発生をカウントします)、データを64回(可能なトリヌクレオチドごとに1回)通過する必要があるため、非常に非効率的です。

私の質問は、bashまたはgrepを使用して、ファイルの1回のパスで各トリヌクレオチドをカウントする方法がありますか(ファイルが非常に大きいため)?

どうも

5
IFS=$'\n'
gzip -dc file.gz | grep -v '^>' | grep -Foe "${tri[*]}" | sort | uniq -c

ちなみに、AAACAAAAACの両方に一致しますが、grep -oはそのうちの1つだけを出力します。それはあなたが望むものですか?また、AAAでのAAAAAAの出現回数は? 2または4([AAA]AAAA[AAA]AAAA[AAA]AAAA[AAA])?

多分あなたは代わりに欲しい:

gzip -dc file.gz | grep -v '^>' | fold -w3 | grep -Fxe "${tri[*]}" | sort | uniq -c

これは、行を3文字のグループに分割し、出現回数を完全な行としてカウントします(AAAACAAATTCGの出現回数を0回検出します(これはACA AAT TCG))。

またはその一方で:

gzip -dc file.gz | awk '
  BEGIN{n=ARGC;ARGC=0}
  !/^>/ {l = length - 2; for (i = 1; i <= l; i++) a[substr($0,i,3)]++}
  END{for (i=1;i<n;i++) printf "%s: %d\n", ARGV[i], a[ARGV[i]]}' "${tri[@]}"

AAAAAAAAAが4回出現します)。

4

@stéphane-chazelasの2番目の例は素晴らしいですが、sortコマンドは、データが大きくなるにつれてこれを実際に遅くする可能性があります。

非ヘッダー行の文字が有効なヌクレオチドであると想定できますか?これにより、triの一致が削除されます。

gzip -dc file.gz | grep -v '^>' | fold -w3 | awk '{a[$0]++} END{for(codon in a) {printf "%s: %d\n", codon, a[codon]}'

関連する注記として、3ヌクレオチドトークンを2バイトの8進数(またはそこから2進数)に変換すると、データストリームのサイズが2/3または1/3減少します。

gzip -dc file.gz | grep -v '^>' | tr ACGT 0123 | fold -w3 | cat <(echo "obase=8; ibase=4;" ) - | bc | xargs printf "%02d\n" | tee foo.octal | xxd -r -p > foo.bin

ヌクレオチドに戻る

cat foo.bin | xxd -p | fold -w2 | cat <(echo "obase=4; ibase=8;") - | bc | xargs printf "%03d" | tr 0123 ACGT

xargsはおそらくここでの制限ステップであり、おそらく一度にN行を解析することでそれを修正するか、gnuparallelを使用するでしょう。

0
Dave