问题是您正在复制要在这一行中使用的哈希值:
my %h2 = %{$hRef};
这是可以理解的,因为这里的许多帖子都使用这个习惯用法来为哈希创建本地名称,而没有解释它实际上是在制作副本。
在 Perl 中,哈希是复数值,就像数组一样。这意味着在列表上下文中(例如分配给哈希时得到的),聚合将被分解为其内容列表。然后,这个对列表被组装成一个新的散列,如图所示。
您想要做的是直接使用参考。
for (keys %$hRef) {...}
for (values %$href) {...}
my $x = $href->{some_key};
# or
my $x = $$href{some_key};
$$href{new_key} = 'new_value';
当使用普通散列时,您有一个印记,它可以是%
当谈论整个哈希时,$
当谈论单个元素时,并且@
当谈论切片时。每个符号后面都跟着一个标识符。
%hash # whole hash
$hash{key} # element
@hash{qw(a b)} # slice
使用名为的参考$href
只需替换字符串hash
在上面的代码中$href
。换句话说,$href
是标识符的完整名称:
%$href # whole hash
$$href{key} # element
@$href{qw(a b)} # slice
其中每一个都可以写成更详细的形式:
%{$href}
${$href}{key}
@{$href}{qw(a b)}
这又是字符串的替换'$href'
for 'hash'
作为标识符的名称。
%{hash}
${hash}{key}
@{hash}{qw(a b)}
在使用元素时,您还可以使用取消引用箭头:
$hash->{key} # exactly the same as $$hash{key}
但我更喜欢双印记语法,因为它类似于整个聚合和切片语法,以及正常的非引用语法。
总而言之,任何时候你写这样的东西:
my @array = @$array_ref;
my %hash = %$hash_ref;
您将复制每个聚合的第一层。直接使用取消引用语法时,您将处理实际值,而不是副本。
如果您想要哈希的真实本地名称,但想要处理相同的哈希,您可以使用local
关键字来创建别名。
sub some_sub {
my $hash_ref = shift;
our %hash; # declare a lexical name for the global %{__PACKAGE__::hash}
local *hash = \%$hash_ref;
# install the hash ref into the glob
# the `\%` bit ensures we have a hash ref
# use %hash here, all changes will be made to $hash_ref
} # local unwinds here, restoring the global to its previous value if any
这是纯粹的 Perl 别名方式。如果你想使用my
变量来保存别名,您可以使用该模块Data::Alias