ここでの問題は、ほぼ間違いなくクオート補間です。「シェルアウト」するたびに、引用符の別のレイヤーをアンラップします。引用符の中で何をするかは、二重引用符を使用しているかどうかの問題です"
-補間するか、単一引用符を使用してから、次のシェル'
に渡す前にそれをリテラルとして扱います。
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 を実行するよりもはるかに多くの範囲と柔軟性が得られるからです。