我试图编写脚本来下载我的CVS模块及其各自的依赖项,我将项目组织成我的Perl脚本的哈希:
$num_args = $#ARGV + 1;
$products = {
'productName' => {
'repository1' => ('module1', 'module2'),
'repository2' => ('module3', 'module4', 'module5'),
'repository3' => ('module6', 'module7')
}
};
if ($num_args <= 2) {
print "($num_args) Insufficient arguments!\n";
print "Usage: cp-stack.pl PRODUCT_NAME USER [PASSWORD [BRANCH]]\n";
exit;
}
$Product = $ARGV[0];
$User = $ARGV[1];
$Password = '';
$Branch = '';
if ($num_args >= 3) {
$Password = $ARGV[2];
}
if ($num_args >= 4) {
$Branch = $ARGV[3];
}
$productFound = 0;
for my $firstKey (keys %$products) {
my $productName = $firstKey;
my $productHash = $products{$productName};
print "$productName\n";
if ($productName == $Product) {
$productFound = 1;
print "Product '$productName' found!\n";
print $products{$productName} . " keys\n";
for my $secondKey (keys %{ $productHash }) {
#while (my($repository, $modulesList) = each(%$productHash)) {
my $repository = $secondKey;
my $modulesList = $productHash{$repository};
printf("set CVSROOT=:pserver:$User\@mycvsaddr.com:/cvsdirectory/$repository\n");
for my $i (0 .. $#modulesList) {
if ($Branch != '') {
printf("cvs checkout -P -r {$Branch} " . $modulesList[$i] . "\n");
} else {
printf("cvs checkout -P " . $modulesList[$i] . "\n");
}
}
}
}
}
它遇到了Product&#39; name&#39;找到了!但是不要进入模块循环......我无法弄明白为什么。
我是Perl的初学者。
答案 0 :(得分:2)
'repository1' => ('module1', 'module2'),
'repository2' => ('module3', 'module4', 'module5'),
'repository3' => ('module6', 'module7')
与
相同'repository1', 'module1', 'module2', 'repository2', 'module3',
'module4', 'module5', 'repository3', 'module6', 'module7'
所以
$products = {
'productName' => {
'repository1' => ('module1', 'module2'),
'repository2' => ('module3', 'module4', 'module5'),
'repository3' => ('module6', 'module7')
}
};
是一种奇怪的写作方式
$products = {
'productName' => {
'repository1' => 'module1',
'module2' => 'repository2',
'module3' => 'module4',
'module5' => 'repository3',
'module6' => 'module7',
}
};
你永远不会创建任何阵列!您可以使用方括号创建匿名数组。
$products = {
'productName' => {
'repository1' => [ 'module1', 'module2' ],
'repository2' => [ 'module3', 'module4', 'module5' ],
'repository3' => [ 'module6', 'module7' ],
}
};
就像{ }
返回对哈希的引用一样,[ ]
返回对数组的引用。所以
for my $i (0 .. $#modulesList) {
... $modulesList[$i] ...
}
需要
for my $i (0 .. $#$modulesList) {
... $modulesList->[$i] ...
}
或
for my $module (@$modulesList) {
... $module ...
}
答案 1 :(得分:1)
这不是数组散列的散列。
$products = {
'productName' => {
'repository1' => ('module1', 'module2'),
'repository2' => ('module3', 'module4', 'module5'),
'repository3' => ('module6', 'module7')
}
};
展平到
$products = {
'productName' => {
'repository1' => 'module1',
'module2' => 'repository2',
'module3' => 'module4',
'module5' => 'repository3',
'module6', 'module7',
}
};
您需要使用arrayrefs定义数组:[]
$products = {
'productName' => {
'repository1' => ['module1', 'module2'],
'repository2' => ['module3', 'module4', 'module5'],
'repository3' => ['module6', 'module7']
}
};
答案 2 :(得分:0)
通过哈希层次结构的递归下降与您需要在每个节点处理的内容的细节不同。一个是下行哈希的通用,另一个是你想要对数据结构做什么。
这大致是我的基本哈希下行器:
use Carp qw<croak>;
use Params::Util qw<_ARRAY _CODE _HASH _HASH0>;
sub hash_descend (+@);
sub hash_descend (+@) {
croak ( 'Hash value or reference missing' )
# I use _HASH0 here, because I don't really want to yell at the user
# for simply providing an empty set.
unless _HASH0( my $h = shift )
;
return unless %$h;
# also set it up so that it can return tuples of key-paths and values
# [ k_1, k_2, ... , k_n => v ]
my @accum;
my $block = _CODE( $_[0] ) ? shift : sub { push @accum, [ @_ ] };
while ( my ( $k, $v ) = each $h ) {
local $_ = $v;
$block->( @_, $k, $v );
if ( _HASH( $v )) {
hash_descend( $v, $block, @_, $k );
}
}
return unless @accum;
return @accum;
}
一旦我完成了这项工作,我就会编写处理节点的逻辑。我想优化一些你在循环中做的不必要的逻辑,所以我提出了这个:
my $branch_arg = $Branch ? "-r $Branch " : '';
my $command_fmt = "cvs checkout -P $branch_arg%s";
hash_descend( $products => sub {
return unless my $arr = _ARRAY( $_[-1] );
foreach ( @$arr ) {
say sprintf( $command_fmt, $_ );
}
});