我正在尝试创建一个子程序,它将一个数组数组传递给子程序,这样命令就可以在不同的目录中并行运行。
基本上,每个第一个索引都针对每个命令目录对。第二个索引有两个变量:directory和命令本身。
例如,
my @commands;
$commands[0][0] = 'tmp1';#directory
$commands[0][1] = 'echo "ave Maria" > avemaria.txt';#command
但是,我无法弄清楚如何在子程序中引用数据,我已经尝试了“[] {}”的所有可能组合,我可以在许多不同的位置进行思考。我已经阅读了https://perldoc.perl.org/perldsc.html中的perl文档,但无法在此处看到它的适用方式。
#!/usr/bin/env perl
use strict; use warnings; use Cwd;
my $TOP_DIRECTORY = getcwd();
local $SIG{__WARN__} = sub {#kill the program if there are any warnings
my $message = shift;
my $fail_filename = "$TOP_DIRECTORY/$0.FAIL";
open my $fh, '>', $fail_filename or die "Can't write $fail_filename: $!";
printf $fh ("$message @ %s\n", getcwd());
close $fh;
die "$message\n";
};#http://perlmaven.com/how-to-capture-and-save-warnings-in-perl
sub execute {
my $command = shift;
print "Executing Command: $command\n";
if (system($command) != 0) {
my $fail_filename = "$TOP_DIRECTORY/$0.fail";
open my $fh, '>', $fail_filename or die "Can't write $fail_filename: $!";
print $fh "$command failed.\n";
close $fh;
print "$command failed.\n";
die;
}
}
sub run_parallel {
my $command_array_reference = shift;
unless ((ref $command_array_reference) =~ m/ARRAY/) {
print "run_parallel requires an array reference as input.\n";
die;
}
use Parallel::ForkManager;
my $manager = new Parallel::ForkManager(4);
my $START_DIRECTORY = getwd();
foreach my $command (0..scalar @{ $command_array_reference }-1) {
$manager->start and next;
my $dir = @$command_array_reference[$command][0];
chdir $dir or die "Can't chdir to $dir: $!";
execute( @$command_array_reference[$command][1] );
chdir $START_DIRECTORY or die "Can't chdir to $START_DIRECTORY: $!";
$manager->finish;
}
$manager->wait_all_children;#necessary after all lists
}
my @commands;
$commands[0][0] = 'tmp1';#directory
$commands[0][1] = 'echo "ave Maria" > aveMaria.txt';#command
$commands[1][0] = 'tmp2';#directory
$commands[1][1] = 'echo "IN HOC SIGNO VINCES" > xp.txt';#command
run_parallel(\@commands);
此特定配置会产生错误
703404669@ssxfisctimga004:~/Scripts$ perl parallelForkManager_dir.pl
syntax error at parallelForkManager_dir.pl line 38, near "]["
Global symbol "$dir" requires explicit package name at parallelForkManager_dir.pl line 39.
Global symbol "$dir" requires explicit package name at parallelForkManager_dir.pl line 39.
syntax error at parallelForkManager_dir.pl line 40, near "]["
Execution of parallelForkManager_dir.pl aborted due to compilation errors.
如何读取子程序中的目录命令对?
答案 0 :(得分:1)
如果您对数据结构有疑问,Data::Dumper是您的朋友。
use Data::Dumper;
# with your @commands
print Dumper \@commands;
打印
$VAR1 = [
[
'tmp1',
'echo "ave Maria" > aveMaria.txt'
],
[
'tmp2',
'echo "IN HOC SIGNO VINCES" > xp.txt'
]
];
现在我们知道里面有一个带数组引用的数组引用。第一级参考是\@commands
中的反斜杠。它创建了对数组的引用。第二个引用是其中的每个数组引用。
在Perl中,您不能在数组中包含数组,只能引用数组。你分配它们的方式是正确的,但可能会使你感到困惑。
$commands[0][0] = 'tmp1';
$commands[0]->[0] = 'tmp1'; # equivalent
->
是解除引用运算符。多维数据结构不需要它,因为它们总是超出第一个
现在你的子目录中有:
my $command_array_reference = \@commands;
要获取值,请使用箭头。你可以省略其中的大多数,但第一个是必需的。
my $dir = $command_array_reference->[0]->[0];
my $cmd = $command_array_reference->[0]->[1];
如果你想把整个事情作为一个列表,取消引用这样的第一级,告诉Perl $foo->[0]
里面的内容是数组引用:
my ($dir, $cmd) = @{ $command_array_reference->[0] };
我建议您查看perlreftut,perlref和perllol。