如何在Perl包的子例程中修改主脚本中的哈希?
Perl包内子例程修改主脚本哈希的问题解决
问题概述
- 主脚本中定义了哈希
%nonstd - 主脚本调用自定义Perl包
TEST,希望通过包内的tNumber子例程修改该全局哈希(添加元素)
示例代码
主脚本(/tmp/nonstdtest.pl)
#!/usr/bin/perl use lib '/tmp'; use TEST; use Data::Dumper; my %nonstd; tNumber(\%nonstd); print Dumper(\%nonstd);
包文件(/tmp/TEST.pm)
package TEST; use strict; use warnings; use Exporter; our @ISA= qw( Exporter ); our @EXPORT_OK = qw( tNumber ); our @EXPORT = qw( tNumber ); sub tNumber { my $nonstd = shift; $nonstd = %$nonstd; $nonstd{'example'} = 'test_here'; }
报错信息
Global symbol "%nonstd" requires explicit package name at /tmp/TEST.pm line 15. Compilation failed in require at /tmp/nonstdtest.pl line 5. BEGIN failed--compilation aborted at /tmp/nonstdtest.pl line 5.
疑问
如何通过包内的子例程修改主脚本中定义的%nonstd哈希?在同一脚本内无包的情况下该逻辑可正常运行,但使用包时出现错误,期望最终%nonstd包含键值对example/test_here。
解决方案
报错根源是TEST.pm中的错误处理逻辑:
- 主脚本传递的是哈希引用给
tNumber子例程,但你执行了$nonstd = %$nonstd;——这会把哈希引用解引用成键值对列表,赋值给标量$nonstd后,变量存储的是哈希的键值对数量,而非哈希或引用。 - 后续
$nonstd{'example'}试图操作名为%nonstd的哈希,但在strict模式下该哈希未声明,因此触发编译错误。
修改TEST.pm的tNumber子例程,直接通过哈希引用操作原哈希即可:
sub tNumber { my $nonstd_ref = shift; $nonstd_ref->{'example'} = 'test_here'; }
或者保留原变量名,去掉错误的解引用赋值:
sub tNumber { my $nonstd = shift; $nonstd->{'example'} = 'test_here'; }
原理说明
Perl中,传递哈希引用给子例程后,对引用的操作会直接作用于原哈希(引用指向原哈希的内存地址),不需要将引用转换为哈希——转换后会生成哈希副本,修改副本不会影响原哈希。
修改后运行主脚本,会输出包含'example' => 'test_here'的哈希结构,符合预期。
内容的提问来源于stack exchange,提问作者olivierg
相关产品推荐
相关产品推荐

