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 时才执行第一个块:它打印当前处理的记录并跳到下一条记录;
  • 仅当正则表达式与当前处理的记录不匹配时才执行第二个块>:它将当前处理的记录的内容连接到变量x并跳到下一条记录;
  • 仅当正则表达式与当前处理的记录匹配时才执行第三个块>:它打印变量的内容x,后跟换行符,后跟当前处理的记录的内容,并跳到下一条记录;
  • 仅当没有更多记录需要处理时才执行第四块:它打印变量的内容x

我对这个问题的所有答案进行了基准测试,md5sum在系统启动后和发出命令后立即检查 SSD 上的输出文件sudo fstrim -v /,使用以下bash脚本,其中outputfile通过重复以下位置的文件创建了一个约 226MB 的文件:这个链接10万次:

#!/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

相关内容