perl脚本练习:fasta格式与tab格式序列之间相互转换(2
2021-12-07 本文已影响0人
学生信的大叔
前言
我的认知里,fasta格式中“>”
只会位于行首。但是我写脚本用的示例数据里出两行特殊id。这两个id中除了行首的“>”,中间还有“>”,造成原脚本不能适用。所以在脚本里加了个检查,检查是否出了行首还有其它位置有“>”。检查是检查了,但是还没有解决问题。于是没有修改设定分隔符“$/”
的值,而是改成对读入的每行进行检查了。
今天把改后的适用性更广的代码发出来!脚本有点挫,不过问题不大。
使用
跟上一篇代码一样
将fasta格式转换为tab分割
perl fa2tab.pl -fa2tab seqs.fa(input) seqs.fa.tsv(output)
将tab分割的文件转换为fasta格式
perl fa2tab.pl -tab2fa seqs.fa.tsv(input) seqs.fa.tsv.fa(output)
注意事项:脚本和输入文件只能放在当前目录。
代码
#!/usr/bin/env perl
use strict;
my $usage = "Usage:\nperl $0 -fa2tab seqs.fa(input) seqs.fa.tsv(output)\nperl fa2tab.pl -tab2fa seqs.fa.tsv(input) seqs.fa.tsv.fa(output)\n";
my $option = "$ARGV[0]";
die "$usage" unless $option =~ /-fa2tab|-tab2fa/i;#注意优先级;是不是很神奇;
die "$usage" unless @ARGV == 3; #列表上下文
if($option =~ /-fa2tab/i){
open FA,"$ARGV[1]" || die "\nERROR: Couldn't open $ARGV[1] !\n";
my $tmp = "tmp"."$ARGV[2]";
open TMP,'>',$tmp || die "\nERROR: Couldn't open $tmp !\n";
while (<FA>){
if(/\A>/){ #按行首>读入;
chomp;
$_ =~ s/^>//;
print TMP "\n$_\t";#第一行会多一个空行,所以先建了个临时文件;
}else{
chomp;
print TMP "$_";#此处不添加分隔符,而在id序列行前加换行符;
}
}
close FA;
close TMP;
open TMP,$tmp|| die "\nERROR: Couldn't create $tmp !\n";#开始解决空行问题
open TSV,'>',"$ARGV[2]" || die "\nERROR: Couldn't create $ARGV[2] !\n";
while(<TMP>){
next if /^\s+$/;
print TSV $_;
}
print TSV "\n";#R语言read_delim()读入数据框时提示“Files must end with a newline”,所以在文件最后放入一个空行。
close TMP;
close TSV;
unlink $tmp; #删除临时文件;
}elsif($option =~ /-tab2fa/){
open TSV,"$ARGV[1]" || die "\nERROR: Couldn't open $ARGV[1] !\n";
open FA,'>',"$ARGV[2]"|| die "\nERROR: Couldn't create $ARGV[2] !\n";
my ($id, $seq);
while(<TSV>){
next unless (my ($id,$seq) = /(.*?)\t(.*)/s);
chomp $seq; #对于这么短的模块,这么写有点多余了;
print FA ">$id\n$seq\n"; #printf 取格式化输出控制每行序列数,有兴趣的自己改下。
} #应该不用写else了,前面已经限定了只有这两种情况才可执行;
close FA;
close TSV;
}
总结
- 新手写脚本就是在写bug