awkはfastaファイルを操作します。

awkはfastaファイルを操作します。

このようなファイルがあります。

>chr1
ACGTGGC
TGCCGTT
ATCCTTG
>chr2
ACTTTTA
CTCATAA

seqを1つの文字列に変換したいです。次のように出力する必要があります。

>chr1
ACGTGGCTGCCGTTATCCTTG
>chr2
ACTTTTACTCATAA

awkを使ってどうすればよいですか?私はPerlでこれを行う方法を知っています。

ありがとう

答え1

期待どおりに動作します。

awk '/>chr/{if (x)print x;print;x="";next}{x=(!x)?$0:x$0;}END{print x;}' file

>chr1
ACGTGGCTGCCGTTATCCTTG
>chr2
ACTTTTACTCATAA

答え2

awk 'BEGIN{ RS=">[^\n]+\n"; } 
     NR>1{ printf( "%s", rt gensub("\n","","g") "\n" ); }
     { rt=RT; }' myfile

出力:

>chr1
ACGTGGCTGCCGTTATCCTTG
>chr2
ACTTTTACTCATAA

一般的な注意:次の入力データを使用してください。FASTA形式の例そしてそれを繰り返し81.1MBファイルをテストした結果、次のようなtime結果が得られました。

Peter.O      real  0m1.653s   user  0m1.396s   sys  0m0.256s
user2196728  real  0m6.587s   user  0m5.972s   sys  0m0.252s
kos          real  0m12.866s  user  0m12.589s  sys  0m0.268s

結果はすべてのテスト方法でmd5sum同じです。より一般的に機能するには、
user2196728バージョンを変更する必要があります。>chr>

答え3

非常に具体的なファイル形式を使用しているため、最初のレコードは常に次の形式であると仮定します><string>

< inputfile awk 'NR==1 {print;next} !/>/ {x=x$0;next} />/ {print x"\n"$0;x="";next} END {print x}' > outputfile

拡張:

NR==1 {
    print;
    next
}
!/>/ {
    x=x$0;
    next
}
/>/ {
    print x"\n"$0;
    x="";
    next
}
END {
    print x
}
  • 最初のブロックは、現在処理中のレコード番号が1の場合にのみ実行されます。現在処理中のレコードを印刷し、次のレコードにジャンプします。
  • 2番目のブロックは、正規表現が現在処理されているレコードと一致しない場合にのみ実行されます>。現在処理されているレコードの内容を変数にリンクxし、次のレコードにジャンプします。
  • 3番目のブロックは、正規表現が現在処理されているレコードと一致する場合にのみ実行されます>。変数の内容x、改行文字、現在処理されているレコードの内容が順番に印刷され、次のレコードにジャンプします。
  • 4番目のブロックは、処理するレコードがなくなったときにのみ実行されます。変数の内容を印刷しますx

md5sum私はシステムの起動直後にSSDの出力ファイルを確認し、次の場所でファイルを繰り返して〜226MBのファイルを生成する次のスクリプトをsudo fstrim -v /使用bashしてコマンドを実行した後、この質問に対するすべての答えをベンチマークしました。outputfileこのリンク100,000回:

#!/bin/bash

for ((i=0; i<3; i++)); do /usr/bin/time -f "kos\t\treal %e" awk 'NR==1 {print;next} !/>/ {x=x$0;next} />/ {print x"\n"$0;x="";next} END{print x}' outputfile > outputfile1; done
for ((i=0; i<3; i++)); do /usr/bin/time -f "Peter.O\t\treal %e" awk 'BEGIN{ RS=">[^\n]+\n"; }NR>1{ printf( "%s", rt gensub("\n","","g") "\n" ); }{ rt=RT; }' outputfile > outputfile2; done
for ((i=0; i<3; i++)); do /usr/bin/time -f "user2196728\treal %e" awk '/>/{if (x)print x;print;x="";next}{x=(!x)?$0:x$0;}END{print x;}' outputfile > outputfile3; done
md5sum outputfile1 outputfile2 outputfile3

結果は次のとおりです。

~$ sudo fstrim -v /
[sudo] password for user: 
/: 68,8 GiB (73839202304 bytes) trimmed
~$ cd tmp
~/tmp$ bash exe
kos         real 2.55
kos         real 2.57
kos         real 2.55
Peter.O     real 2.93
Peter.O     real 2.92
Peter.O     real 2.92
user2196728 real 2.51
user2196728 real 2.51
user2196728 real 2.68
0618a8077b43eb44eb263d7d6f84777f  outputfile1
0618a8077b43eb44eb263d7d6f84777f  outputfile2
0618a8077b43eb44eb263d7d6f84777f  outputfile3

関連情報