这个问题是关于要求对 Perl 系统中发生的事情进行一些解释,因为尽管我已经编码超过 25 年,但我并没有隐含地看到这一点。所以故事来了……
在尝试使用Cyrus::IMAP::Admin
Perl5 中的实例时,我尝试获取并打印配额列表,从而导致返回的数据结构有些奇怪。
my %quotas = $client->listquota(@list[0]);
if ( $client->error ) {
printf STDERR "Error: " . $client->error . "\n";
exit 1;
}
print "root: " . $list[0] . "\n";
foreach my $quota ( keys %quotas ) {
print( $quota, " ", $quotas{$quota}[0], "/", $quotas{$quota}[1], " KiB\n" );
}
通过打印出类似的内容,此代码实际上可以按需要工作
root: user.myuser
STORAGE: 123/4567 KiB
此代码取自Cyrus::IMAP::Shell
类似于以下内容的阅读:
my %quota = $$cyrref->listquota(@nargv);
foreach my $quota (keys %quota) {
$lfh->[1]->print(" ", $quota, " ", $quota{$quota}[0], "/", $quota{$quota}[1]);
if ($quota{$quota}[1]) {
$lfh->[1]->print(" (", $quota{$quota}[0] * 100 / $quota{$quota}[1], "%)");
}
}
这段代码在我看来有点傻,因为使用$quota{$quota}[0]
. 在我的例子中,我稍微重命名了变量,以拒绝混合使用不同类型但名称相同的变量。
在获取代码之前,Cyrus::IMAP::Admin
我尝试了解其规范并通过自己编写的代码处理结果。它看起来像这样:
my %quotas = $client->listquota(@list[0]);
if ( $client->error ) {
printf STDERR "Error: " . $client->error . "\n";
exit 1;
}
print "root: " . $list[0] . "\n";
foreach my $quota ( keys %quotas ) {
my @sizes = @quotas{$quota};
print( $quota, " ", $sizes[0], "/", $sizes[1], "\n" );
}
但是,这段代码不起作用,我自己也没有找到任何合理的解释。我的理解是,将最后一个代码示例转移到最初发布的表单需要将第 11 行中的分配源替换为第 12 行中的用法,并将配额的标志从 更改@
为 ,$
因为我最终试图获得一个标量结果. 最后一段代码在斜杠之前打印一个数组引用,之后什么也没有。所以我必须像这样修复我的代码才能让它工作:
my %quotas = $client->listquota(@list[0]);
if ( $client->error ) {
printf STDERR "Error: " . $client->error . "\n";
exit 1;
}
print "root: " . $list[0] . "\n";
foreach my $quota ( keys %quotas ) {
my @sizes = @quotas{$quota};
print( $quota, " ", $sizes[0][0], "/", $sizes[0][1], "\n" );
}
第 12 行中的这个额外的取消引用是我现在感到困惑的地方。为什么@sizes
包含一个数组在其唯一的第一个元素中存储另一个数组?由于感到困惑,我已经在第 11 行尝试了替代代码,但无济于事。这些测试包括
my @sizes = $quotas{$quota};
(因为它与上面发布的原始代码等效)和
my $sizes = @quotas{$quota};
(因为我不知道为什么)。切换符号似乎根本不会改变赋值的语义。%quotas
但是使用这个赋值似乎对原来包含的数据结构打开了不同的视图。需要哪些符号才能@sizes
匹配$quotas{$quota}
最顶层代码片段中使用的内容和结构?