通过引用和标量变量传递 Perl 哈希
Posted
技术标签:
【中文标题】通过引用和标量变量传递 Perl 哈希【英文标题】:Passing a Perl Hash by reference plus scalar variable 【发布时间】:2019-06-04 13:13:46 【问题描述】:我试图通过引用和标量值从 Main.pl 传递给子(在 ReadConfigFile.pm 中)哈希。标量变量是配置文件的路径,一旦打开这个文件,我想用它的一些值填充散列。我如何通过引用和标量传递哈希值,以便我可以在 Main.pl 中使用哈希值
我读了很多书,但无法让它发挥作用。我意识到我做不到 = @_;在我的 sub 中,因为它正在创建一个新的哈希。
我尝试了原型方法,这填充了哈希值,但是回到 Main.pl 哈希值是空的。
Main.pl
# Read the config file. Return 3 scalars and a hash
my %apps;
my ($schema, $directory, $staticFile) = readConfigFile(\%apps, $configFilePath);
my %app_list = %apps; # ive tried this in, out and in a variety of states
foreach my $name (sort keys %app_list)
print "\nMAIN $name";
# this is empty
ReadConfigFile.pm
sub readConfigFile (\%$)
my ($apps_ref, $configFilePath) = @_;
# also tried
# $apps_ref = shift but then configFilePath is empty
# linearray is each line from open config file split by :
$apps_ref$lineArray[1]id = $lineArray[1];
$apps_ref$lineArray[1]name = $lineArray[2];
$schema = $lineArray[1];
$directory = $lineArray[1];
$staticFile = $lineArray[1];
return ($schema, $directory, $staticFile);
configFile.txt
APP:1101:ACTIVITY
APP:1102:EVENTS
APP:1103:PERFORMANCE
APP:1104:LOCATION
STATIC_FILE:static_file.sql
SCHEMA:CAASS
DIRECTORY:CAASS
我想获得返回的 3 个标量变量和哈希值,以便我可以在整个 Main.pl 中使用它们并传递给其他子。
我也尝试只传入配置文件名并返回 4 个变量、3 个标量和哈希。
我希望有人会在几分钟内破解这个问题,但我无法计算出 \ 和 @ 以及 % 和 $ 的组合来使其工作。
感谢任何帮助或想法。
编辑 1: main.pl
my %apps;
my ($schema, $directory, $staticFile) = readConfigFile(\%apps, $configFilePath);
foreach my $name (sort keys %apps)
print "\nMAIN $name";
读取配置文件
sub readConfigFile ()
my $apps_ref = shift;
my $configFilePath = $_[0];
#Fill It
$apps_ref$lineArray[1]id = $lineArray[1];
$apps_ref$lineArray[1]name = $lineArray[2];
# This shows results
foreach my $name (sort keys %apps_ref)
print "\nreadConfigFile $name";
但值并没有回到 Main.pl
编辑 2: 所以我仍然对如何使上述内容起作用感兴趣。但是我以不同的方式攻击它并且它有效
Main.pl
my ($schema, $directory, $staticFile, %apps) = readConfigFile($configFilePath);
foreach my $name (sort keys %apps)
print "\nMAIN $name";
读取配置文件
sub readConfigFile ()
my $configFilePath = $_[0];
my %apps;
#Fill It
%apps$lineArray[1]id = $lineArray[1];
$apps$lineArray[1]name = $lineArray[2];
foreach my $name (sort keys %apps)
print "\nreadConfigFile $name";
return ($schema, $directory, $staticFile, %apps);
两者都启动输出显示。
【问题讨论】:
use strict;
use warnings;
始终使用use strict; use warnings qw( all );
!!!它会发现问题
所有这些错误都引起了我的注意,因为我添加了 use strict;并使用警告;如果不打开它们,它就可以工作,所以毫无疑问!
【参考方案1】:
Perl* 中没有隐式的“按引用传递”。一切都以相同的方式传递 - 作为标量列表,通过别名(因此传递哈希本身将传递其键和值的列表*)。但是您可以创建一个引用,传递它,然后取消引用它以使用它 - 并且可以复制引用而不复制底层结构。
use strict;
use warnings;
my %hash;
my $ref = \%hash;
my $copy = $ref;
$copy->a = 1;
print "$ref->a\n"; # also 1
在子例程中分配my (...) = @_;
或my $foo = shift;
之后,引用将保持其引用结构。
use strict;
use warnings;
sub foo
my ($ref, $key) = @_;
$ref->$key = 42;
my %hash;
foo(\%hash, 'foo');
print "$hashfoo\n"; # 42
有关 Perl 参考的相关文档,请参阅 https://p3rl.org/REF。
由于您已经传递了引用,因此不需要您的 (\%$)
原型:您可以将其从子例程定义中删除。
*除了原型,但在大多数情况下最好避免使用它们。
【讨论】:
我不理解您的代码,但是当变量被传递给子程序并再次返回时,它让我更加困惑。您能否扩展您的答案,并告诉我如何从一个子中获取 2 个变量。谢谢 @DavidJanes 我添加了一个示例,这有帮助吗?确保不要在子程序定义中使用()
,这仍然是一个原型,不会做你想做的事情。
Re "Perl 中没有隐式的'传递引用'",恰恰相反,一切都是通过引用传递的。 (不过,您必须记住,只有标量可以传递给 subs。)
@ikegami 这就是我想说的,但可能解释得很糟糕 - 没有功能可以这样做,因为它总是会发生,但只有通过标量。以上是关于通过引用和标量变量传递 Perl 哈希的主要内容,如果未能解决你的问题,请参考以下文章