Perl:为变量分配 3 个可能值之一
Perl: Assigning a variable one of 3 possible values
我有一个 DNA 序列。我们称它为 "ATCG"。我在 2 个单独的文件中有 2 个小型 DNA 序列数据库,我们将其称为 "db1.txt" 和 "db2.txt"。两个数据库的格式如下:
>name of sequence
EXAMPLESEQUENCEATCGATCG
>name of another sequence
ASECONDEXAMPLESEQUENCEATCGATCG
我想知道我的 DNA 序列是否包含在其中一个数据库中,如果包含在哪个数据库中。那么,我的结果有 3 个可能的值:我的序列既不在数据库中,也不在 db1 中,也不在 db2 中。这是我的代码:
use warnings;
use strict;
my $entry = 'ATCG';
my $returnval = "The sequence is from neither database";
#if in db1
my $name1;
my $seq1;
open (my $database1, "<", "db1.txt") or die "Can't find db1";
while (<$database1>){
chomp ($name1 = <$database1>);
chomp ($seq1 = <$database1>);
if (
index($seq1, $entry) != -1
|| index($entry, $seq1) != -1
) {
$returnval = "The sequence is from db1: ". $name1;
last;
}
}
#If in db2:
my $name2;
my $seq2;
open (my $database2, "<", "db2.txt") or die "Can't find db2";
while (<$database2>){
chomp ($name2 = <$database2>);
chomp ($seq2 = <$database2>);
if(
index($seq2, $entry) != -1
|| index($entry, $seq2) != -1
) {
$returnval = "The sequence is from db2: ". $name2;
last;
}
}
print $returnval . "\n";
此代码存在一些问题(可能不止几个)。不管我的序列是什么, $returnval = "The sequence is from db2: " 最后都没有名字。此外,$name2 和 $seq2 似乎是未初始化的值,即使代码与 db1 的代码相同。如果我删除了用于测试 db2 的整个部分,代码只有 returns "the sequence is from db1: " 后跟我从数据库复制和粘贴的 some 序列的适当名称,而对其他人来说 returns "the sequence is from neither database"。
我做错了什么?如何修复未初始化的值,为什么 db2 的代码不起作用?
编辑:
我忘了提到输出序列在 db2 中优先于输出它在 db1 中,如果一个序列在两者中。
主要问题出在 while 循环的条件上,它每次迭代读取并丢弃一行,并防止 $name
和 $seq
变量每次都包含名称和序列。删除该条件并将文件结尾检查放在循环内应该可以解决问题。也可以遍历两个数据库并对两者应用相同的逻辑,因此您只需要一个循环来检查每个文件的内容。
use warnings;
use strict;
my $entry = 'ATCG';
my $returnval = "The sequence is from neither database";
my @files = qw(db2 db1);
FILE:
for my $file (@files) {
open my $fh, '<', "$file.txt" or die "Error opening $file: $!";
while (1) {
my $name = <$fh>;
my $seq = <$fh>;
if (not defined $seq) {
warn "Odd number of lines in $file" if defined $name;
last; # Reached end of file
}
chomp($name, $seq);
if (
index($seq, $entry) != -1
or index($entry, $seq) != -1
) {
$returnval = "The sequence is from $file: $name";
last FILE; # No need to search the others
}
}
}
print "$returnval\n";
我会将比较包含在子例程中,尤其是因为您必须多次执行相同的操作
此解决方案实现了子例程 matches
,其中 returns 文件中匹配序列的名称,如果不是,则为 false 值找到
我已将记录分隔符 $/
更改为 >
字符,以便自动拆分序列,每条记录由名称组成,直到第一个换行符,然后是序列。 tr/\n//d
调用从序列中删除任何换行符(因此它将处理 FAST 格式支持的多行序列)并对每个序列进行比较
调用代码只是使用一个for
循环来为每个文件名调用子程序。一旦找到匹配项,循环就会退出,将 $name
和 $file
设置为匹配项的详细信息
根据$name
是否为真
构建并打印消息
use strict;
use warnings 'all';
use feature 'say';
my $entry = 'ATCG';
my ($file, $name);
for $file ( qw/ db2 db1 / ) {
last if $name = matches($entry, "$file.txt");
}
say $name ?
"The sequence is from $file: $name" :
"The sequence is from neither database";
sub matches {
my ($seq, $file) = @_;
open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!};
local $/ = '>';
while ( <$fh> ) {
chomp;
my ($name, $file_seq) = split /\n/, $_, 2;
$file_seq =~ tr/\n//d;
return $name if index($file_seq, $seq) >= 0 or index($seq, $file_seq) >= 0;
}
return;
}
我有一个 DNA 序列。我们称它为 "ATCG"。我在 2 个单独的文件中有 2 个小型 DNA 序列数据库,我们将其称为 "db1.txt" 和 "db2.txt"。两个数据库的格式如下:
>name of sequence
EXAMPLESEQUENCEATCGATCG
>name of another sequence
ASECONDEXAMPLESEQUENCEATCGATCG
我想知道我的 DNA 序列是否包含在其中一个数据库中,如果包含在哪个数据库中。那么,我的结果有 3 个可能的值:我的序列既不在数据库中,也不在 db1 中,也不在 db2 中。这是我的代码:
use warnings;
use strict;
my $entry = 'ATCG';
my $returnval = "The sequence is from neither database";
#if in db1
my $name1;
my $seq1;
open (my $database1, "<", "db1.txt") or die "Can't find db1";
while (<$database1>){
chomp ($name1 = <$database1>);
chomp ($seq1 = <$database1>);
if (
index($seq1, $entry) != -1
|| index($entry, $seq1) != -1
) {
$returnval = "The sequence is from db1: ". $name1;
last;
}
}
#If in db2:
my $name2;
my $seq2;
open (my $database2, "<", "db2.txt") or die "Can't find db2";
while (<$database2>){
chomp ($name2 = <$database2>);
chomp ($seq2 = <$database2>);
if(
index($seq2, $entry) != -1
|| index($entry, $seq2) != -1
) {
$returnval = "The sequence is from db2: ". $name2;
last;
}
}
print $returnval . "\n";
此代码存在一些问题(可能不止几个)。不管我的序列是什么, $returnval = "The sequence is from db2: " 最后都没有名字。此外,$name2 和 $seq2 似乎是未初始化的值,即使代码与 db1 的代码相同。如果我删除了用于测试 db2 的整个部分,代码只有 returns "the sequence is from db1: " 后跟我从数据库复制和粘贴的 some 序列的适当名称,而对其他人来说 returns "the sequence is from neither database"。
我做错了什么?如何修复未初始化的值,为什么 db2 的代码不起作用?
编辑: 我忘了提到输出序列在 db2 中优先于输出它在 db1 中,如果一个序列在两者中。
主要问题出在 while 循环的条件上,它每次迭代读取并丢弃一行,并防止 $name
和 $seq
变量每次都包含名称和序列。删除该条件并将文件结尾检查放在循环内应该可以解决问题。也可以遍历两个数据库并对两者应用相同的逻辑,因此您只需要一个循环来检查每个文件的内容。
use warnings;
use strict;
my $entry = 'ATCG';
my $returnval = "The sequence is from neither database";
my @files = qw(db2 db1);
FILE:
for my $file (@files) {
open my $fh, '<', "$file.txt" or die "Error opening $file: $!";
while (1) {
my $name = <$fh>;
my $seq = <$fh>;
if (not defined $seq) {
warn "Odd number of lines in $file" if defined $name;
last; # Reached end of file
}
chomp($name, $seq);
if (
index($seq, $entry) != -1
or index($entry, $seq) != -1
) {
$returnval = "The sequence is from $file: $name";
last FILE; # No need to search the others
}
}
}
print "$returnval\n";
我会将比较包含在子例程中,尤其是因为您必须多次执行相同的操作
此解决方案实现了子例程 matches
,其中 returns 文件中匹配序列的名称,如果不是,则为 false 值找到
我已将记录分隔符 $/
更改为 >
字符,以便自动拆分序列,每条记录由名称组成,直到第一个换行符,然后是序列。 tr/\n//d
调用从序列中删除任何换行符(因此它将处理 FAST 格式支持的多行序列)并对每个序列进行比较
调用代码只是使用一个for
循环来为每个文件名调用子程序。一旦找到匹配项,循环就会退出,将 $name
和 $file
设置为匹配项的详细信息
根据$name
是否为真
use strict;
use warnings 'all';
use feature 'say';
my $entry = 'ATCG';
my ($file, $name);
for $file ( qw/ db2 db1 / ) {
last if $name = matches($entry, "$file.txt");
}
say $name ?
"The sequence is from $file: $name" :
"The sequence is from neither database";
sub matches {
my ($seq, $file) = @_;
open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!};
local $/ = '>';
while ( <$fh> ) {
chomp;
my ($name, $file_seq) = split /\n/, $_, 2;
$file_seq =~ tr/\n//d;
return $name if index($file_seq, $seq) >= 0 or index($seq, $file_seq) >= 0;
}
return;
}