这里的问题几乎可以肯定是引用插值。每次您“掏出”时,您都会打开另一层引号。它在引号内的作用是一个问题,即您是在使用双引号"
- 它是插值还是单引号'
,然后在传递到下一个shell 之前将其视为文字。
查看perlop
perl 如何引用。我建议您尝试组装这样的命令:
my $parallel = q{parallel --block 50k --recstart '>' --pipe};
my $outfmt = q{'7 sseqid sstart send sframe bitscore qseqid'};
print $parallel,"\n";
print $outfmt,"\n";
my $command = "cat $TMP/prot$$.fa | $parallel \\ tblastn -db $BLASTDB -query - -word_size 6 -outfmt $outfmt -max_target_seqs 5 -seg yes -lcase_masking > $TMP/blast$$";
print $command;
system ( $command );
(显然在将它传递给系统之前检查您的“命令”是否正确)
但是我可以建议一种不同的方法吗?怎么样而不是嵌入cat
,parallel
你可以在perl
.
我很害怕我对你正在运行的命令并不完全熟悉,但它会是这样的:
#!/usr/bin/perl
use strict;
use warnings;
open( my $input, "<", "$TMP/prot$$.fa" ) or die $!;
my $fork_manager = Parallel::ForkManager->new($THREADS);
while ( my $line = <$input> ) {
$fork_manager->start and next;
chomp $line;
system(
"tblastn -db $BLASTDB -query $line \\
-word_size 6 -max_target_seqs 5 -seg yes -lcase_masking \\
-outfmt \"7 sseqid sstart send sframe bitscore qseqid\"\\
> $TMP/blast$$"
) && die "Can't run tblastn\n";
$fork_manager->finish;
}
close ( $input );
如果需要输出合并,我可能会改用线程:
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open2;
use threads;
use Thread::Queue;
my $num_threads = 8;
my $work_q = Thread::Queue -> new();
my $results_q = Thread::Queue -> new();
sub worker {
open2 ( my $blast_out, my $blast_in, "tblastn -db $BLASTDB -query - -word_size 6 -outfmt '7 sseqid sstart send sframe bitscore qseqid' -max_target_seqs 5 -seg yes -lcase_masking");
while ( my $query = $work_q -> dequeue ) {
print {$blast_in} $query;
$results_q -> enqueue ( <$blast_out> ); #one line - you'll need something different for multi-line results.
}
close ( $blast_out );
close ( $blast_in );
}
sub collate_results {
open ( my $output, "$TMP/results.$$" ) or die $!;
while ( my $result = $results_q -> dequeue ) {
print {$output} $result,"\n";
}
close ( $output );
}
my @workers;
for (1..$num_threads) {
push ( @workers, threads -> create ( \&worker ) );
}
my $collator = threads -> create ( \&collate_results );
open( my $input, "<", "$TMP/prot$$.fa" ) or die $!;
while ( my $line = <$input> ) {
chomp $line;
$work_q -> enqueue ( $line );
}
close ( $input );
$work_q -> end;
foreach my $thr ( @workers ) {
$thr -> join();
}
$results_q -> end;
$collator -> join;
现在我很欣赏这两个可能看起来有点复杂和复杂。但是它们更多地是关于如何将 perl 扩展到并行执行的示例,因为这样做与运行 perl 相比,您拥有更多的范围和灵活性,但要“全力以赴”去做事情。