在Perl中,如果变量保存另一个变量的名称,如何使用第一个变量访问另一个变量?
例如,让
$name = "bob";
@bob = ("jerk", "perlfan");
我应该如何使用$ name来了解bob是什么类型的人? 虽然我不太确定,但我模糊的记忆告诉我它可能与typeglob有关。
答案 0 :(得分:18)
有几点:
有关参考文献的更多信息,请参阅perlreftut(符号和其他)。 有关使用数据结构的帮助,请参阅perldsc。 有关typeglobs的更多信息,请参阅perlmod。 有关词汇变量的更多信息,请参阅perlsub。
以下是使用锁定哈希根据变量内容控制对数据的访问的示例:
use strict;
use warnings;
use Hash::Util qw( lock_hash unlock_hash );
my %data;
lock_hash( %data );
#Altering %data is a fatal exception.
unlock_hash( %data );
%data = (
'bob' => [ 'jerk', 'genius' ],
);
lock_hash( %data );
for my $name (qw/ bob margaret /) {
my $info = $data{$name}; # Fatal error when accessing data for margaret.
print "$name is a\n";
print map "\t$_\n", @$info;
}
除了所有警告之外,使用符号引用的语法应该是你需要使用它(但你不会):
use strict;
use warnings;
my $name = 'bob';
our @bob = qw/jerk genius/;
my $qualities;
{ no strict 'refs';
print "$name: ", @$name, "\n";
$qualities = \@$name;
}
print "$name is a @$qualities\n";
请注意,数组@bob
是使用our
声明的。符号引用仅适用于符号表中的值。换句话说,词法变量不适用于符号引用。
如果我没有强调这一点, 不要使用符号引用 。
答案 1 :(得分:13)
这是非常糟糕的做法。如果曾需要这样做,则意味着您应该重构代码。也许带有命名键的哈希会更好:
my %data = (
'bob' => [ 'jerk', 'perlfan' ],
);
my $name = 'bob';
print $data{ $name }->[0], "\n";
print $data{ $name }->[1], "\n";
my $stringified = join ' and ', @{ $data{ $name } };
print $stringified, "\n";
答案 2 :(得分:4)
请参阅perldoc -q "variable name"
:
初学者通常认为他们希望变量包含变量的名称。 ...
简答:不要。答案很长:阅读FAQ条目(也可在您的计算机上找到)。更长的答案:阅读MJD的Why it's stupid to "use a variable as a variable name"(Part 2,Part 3)。
答案 3 :(得分:3)
你真的不应该这样做,请参阅depesz对替代方案的回答,但是......
{
no strict 'refs';
print join(q{, }, @$name);
}
是的,您可以使用字符串标量作为变量引用,并按名称查找变量。
您也可以使用typeglobs执行此操作,请参阅符号模块以获得简单的方法。
答案 4 :(得分:2)
通常当您认为需要使用符号引用时,使用哈希(关联数组)可以更好地服务。
use strict;
use warnings;
my %user = (
'bob' => [qw' jerk perlfan '],
'mary' => 'had a little lamb',
);
{
for my $name (qw'bob mary susan'){
if( exists $user{$name} ){
if( ref($user{$name}) eq 'ARRAY' ){
print join( ' ', @{$user{$name}} ), "\n";
}else{
print $name, ' ', $user{$name}, "\n";
}
}else{
print "$name not found\n";
}
}
}
结果:
jerk perlfan mary had a little lamb susan not found
如果您认为真的需要使用符号引用,那么这是一种更安全的方法。
use strict;
use warnings;
# can't use my
our @bob = ("jerk", "perlfan");
our $mary = 'had a little lamb';
{
for my $name (qw'bob mary susan'){
if( exists $::{$name} ){
my $ref = $::{$name};
if( *{$ref}{ARRAY} ){
print join(' ',@$ref), "\n";
}elsif( *{$ref}{SCALAR} ){
print "# $name is not an array, it's a scalar\n";
print $name, ' ', $$ref, "\n";
}
}else{
print "$name not found\n"
}
}
}
返回:
jerk perlfan # mary is not an array, it's a scalar mary had a little lamb susan not found
你应该注意到安全的符号引用更难,这就是你不应该使用它们的原因。
除非你当然是专家做一些先进的事。
答案 5 :(得分:0)
no strict 'refs';
print "$name is @$name\n";
答案 6 :(得分:0)
符号引用值得避免,但如果您真的想要使用它们,它们的使用语法与常规引用相同:请参阅http://perlmonks.org/?node=References+quick+reference。