通过引用和标量变量传递 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 哈希的主要内容,如果未能解决你的问题,请参考以下文章

Perl引用介绍

如何将哈希传递给 Perl 中的函数?

请问怎么给perl里的标量,哈希,数组赋初值?

5-Perl 变量

Perl:标量,数组,哈希

perl 第六弹 变量 II