我在Perl中很新,我很困惑如何完成这项任务。我有两个文件:
这里我给出了我的两个文件的一小部分:
Seq.txt包含:
'>' SCO0700, probable ABC transporter protein, ATP-binding component.
MASSMEKPLDHRYRGEHPIRTLVYLFRADRRRLAGAVAVFTVKHSPIWLLPLVTAAIVDT
VVQHGPITDLWTSTGLIMFILVVNYPLHLLYVRLLYGSVRRMGTALRSALCTRMQQLSIG
'>' SCO0755, putative ABC transporter 797720:799942 forward MW:79858
VSTAQETRGRRRAAPPRRSVPKSRARTVRTPTVLQMEAVECGAASLAMVLGHYGRHVPLE
ELRIACGVSRDGSRASNLLKAARSYGFTAKGMQMDLAALAEVTAPAILFWEFNHYVVYDG
'>' SCO2305,putative ABC transporter ATP-binding subunit 2474063:2474989 forward MW:32345
MRPTEGTTPAVAFTGAAKAYGDVRAVDGVDLRIGCGETVALLGRNGAGKSTTIALLLGLC
PPDAGTVELFGGPAERAVRAGRVGAMLQEARAVPRVTVGELVAFVAGRYPAPMPVGQALE
'>' SCO1144, putative ABC transporter ATP-binding protein 1202480:1204282 reverse MW:64637
MHPDRESAWTAPADAVEQPRQVRRILKLFRPYRGRLAVVGLLVGAASLVSVATPFLLKEI
LDVAIPEGRTGLLSLLALGMIFGAVLTSVFGVLQTLISTTVGQRVMHDLRTAVYGRLQQM
'>' SCO1148, putative ABC transporter 1207772:1209553 forward MW:63721
MIGVAPPSYDPAAPTTANTLPVGARPTVRAYVGELLRRHRRAFLFLVTVNTVAVIASMAG
PYLLGGLVERVSDDARELRLGLTATLFVLALVVQAVFVREVRLRGAVLGERMLADLREDF
PID.txt包含:
SCO0755
SCO1144
我编写的代码:
open (PID, 'PID.txt');
my @PID = '<'PID'>';
close(PID);
open (MSD, 'Seq.txt');
my @MSD = '<'MSD'>';
close(MSD);
chomp(@MSD);
my $MSD=join (' ', @MSD);
print "$MSD \n";
for ($i = 0; $i<=2; $i++) {
my $a=$PID[$i];
if ($MSD =~ m/$a(.*?)>/) # ">" end of the string
{
print "$1 \n";
$output= ">".$a.$1;
print $output;
open (MYFILE, '>>data.txt');
print MYFILE "$output\n";
close (MYFILE);
}
}
为什么不识别$a
?如果我放置[ $ a ],那么绑定操作符会识别$a
但不返回我想要的序列(ID存储在$a
中),而是返回第一个序列
我期望的结果是:
'>' SCO0755, putative ABC transporter 797720:799942 forward MW:79858
VSTAQETRGRRRAAPPRRSVPKSRARTVRTPTVLQMEAVECGAASLAMVLGHYGRHVPLE
ELRIACGVSRDGSRASNLLKAARSYGFTAKGMQMDLAALAEVTAPAILFWEFNHYVVYDG
'>' SCO1144, putative ABC transporter ATP-binding protein 1202480:1204282 reverse MW:64637
MHPDRESAWTAPADAVEQPRQVRRILKLFRPYRGRLAVVGLLVGAASLVSVATPFLLKEI
LDVAIPEGRTGLLSLLALGMIFGAVLTSVFGVLQTLISTTVGQRVMHDLRTAVYGRLQQM
答案 0 :(得分:3)
首先,不要在代码中使用$a
和$b
。它们是仅在sort
块内有意义的特殊变量;在其他地方避免使用它们,改为使用有意义的变量名称。
其次,
my @PID = '<'PID'>';
假设您正在尝试将文件句柄PID的内容读入数组,您的意思是:
my @PID = <PID>;
第三,最近常见的最佳做法是使用3-arg open和lexical文件句柄,例如:
open(my $pidfh, '<', 'PID.txt') or die "...";
my @PID = <$pidfh>;
close $pidfh;
您的脚本顶部是否有use strict;
?
为了它的价值,我会将您感兴趣的PID读入哈希以便于查找,然后循环访问Seq.txt;记住你正在查看的条目并存储其内容;每次看到新条目时,查看您构建的上一个条目是否是您想要的条目,如果是,请打印它。这样你就不需要在内存中保存文件的内容,如果它是一个非常大的文件,这将非常有用。
大致类似于以下内容:
#!/usr/bin/perl
use strict;
# Read in a list of PIDs we're interested in
my %want_pid;
open(my $pidfh, '<', 'PID.txt') or die "Failed to open PID.txt - $!";
while (my($pid) = <$pidfh> =~ m{([A-Z0-9]+)}) {
$want_pid{$pid}++ if $pid;
}
# Now process the file and print entries we want
open(my $seqfh, '<', 'Seq.txt') or die "Failed to open Seq.txt - $!";
my $current_pid;
my $current_text;
while (my $line = <$seqfh>) {
if (my ($new_pid) = $line =~ m{^ '>' \s+ ([A-Z0-9]+) , }x) {
# We're at the start of a new entry; if the last one is one we want,
# print it.
if ($want_pid{$current_pid}) {
print $current_text;
}
$current_pid = $new_pid;
$current_text = $line;
} else {
# It's a continuation of an entry
$current_text .= $line;
}
}
close $seqfh;
(改进的空间,但它应该让你走上正确的轨道。)
答案 1 :(得分:2)
我无法告诉你为什么你得到你得到的输出,因为你发布的代码不是有效的Perl而且不会编译或运行 - my @PID = '<'PID'>';
在语法上是无效的。 (它应该是my @PID = <PID>;
,没有任何引号。)因此,显然不是您运行的代码来生成这些结果。
你没有得到任何匹配的原因是,虽然发布的代码确实chomp(@MSD)
,但它也不是chomp(@PID)
,所以PID只有在它们后跟一个时才会匹配新队。在发布的数据中,它们不是。 (而且,即使它们是,chomp(@MSD)
也会删除它们。)
修复此问题会让您向前迈进一步,但仍然无法产生您想要的结果,因为您的正则表达式是错误的。请尝试使用此代码(将$a
重命名为$target
,因为a:这是一个更有意义的名称,而b:$a
和$b
是魔术,所以你不应该使用它们):m/'>' $target([^']*)/
最后,您的for ($i...)
循环不正确,这是使C风格for
犯下的一个非常容易犯的错误。更好的是使用for (list)
代替。
修复所有这些内容,以及切换到词法文件句柄和open
的三参数形式(正如David Precious已经提到的那样)并进行一些通用代码清理,给出了:
#!/usr/bin/env perl
use strict;
use warnings;
open my $pid_fh, '<', 'PID.txt';
my @PID = <$pid_fh>;
close $pid_fh;
chomp(@PID);
open my $msd_fh, '<', 'Seq.txt';
my @MSD = <$msd_fh>;
close $msd_fh;
chomp(@MSD);
my $msd = join(' ', @MSD);
my $output;
open my $outfile, '>>', 'data.txt';
for my $target (@PID) {
if ($msd =~ m/'>' $target([^']*)/) {
$output = ">" . $target . $1;
print $output, "\n";
print $outfile "$output\n";
}
}
...产生输出:
>SCO0755, putative ABC transporter 797720:799942 forward MW:79858 VSTAQETRGRRRAAPPRRSVPKSRARTVRTPTVLQMEAVECGAASLAMVLGHYGRHVPLE ELRIACGVSRDGSRASNLLKAARSYGFTAKGMQMDLAALAEVTAPAILFWEFNHYVVYDG
>SCO1144, putative ABC transporter ATP-binding protein 1202480:1204282 reverse MW:64637 MHPDRESAWTAPADAVEQPRQVRRILKLFRPYRGRLAVVGLLVGAASLVSVATPFLLKEI LDVAIPEGRTGLLSLLALGMIFGAVLTSVFGVLQTLISTTVGQRVMHDLRTAVYGRLQQM
选择正确的序列;我将完全按照您的要求将其格式化为读者的练习。
答案 2 :(得分:0)
测试这是否适合您:
use warnings;
use strict;
die "Usage: $0 <pid file> <seq file>\n" unless @ARGV == 2;
open my $pid, "<", $ARGV[0] or die "Error: Cannot open file $ARGV[0]: $!\n";
open my $seq, "<", $ARGV[1] or die "Error: Cannot open file $ARGV[1]: $!\n";
my %pid = ();
while ( <$pid> ) {
chomp;
s/^\s*(\S*)\s*$/$1/;
++$pid{$_};
}
$/ = "\'>\'";
foreach ( <$seq> ) {
$_ = substr $_, 0, -3;
my ($p) = split /\,/;
$p =~ /(\S+)/;
print "'>'", $_ if exists $pid{$1};
}
此致