变量名中的perl变量替换

问题描述:

#!/usr/bin/perl 
my $var_a; 
$sub_a = "a"; 
$var_a = "a"; 
print ${var_."$sub_a"},"\n"; 


$sub_b = "b"; 
$var_b = "b"; 
print ${var_."$sub_b"},"\n"; 

__DATA__ 

b 

为什么要打印b,但不是?这对我来说似乎是非常意想不到的行为。变量名中的perl变量替换

我正在尝试使用具有替代名称的变量。在实践中,我不能只声明变量,因为赋值是在forloop中完成的,因此具有不同的词汇范围。

+0

'为什么会发生这种情况?'定义“这个”?与其询问如何操作“黑客”,您应该询问您的问题以及如何正确执行。使用字符串作为引用违反'strict'编译指示,应该避免。 – TLP 2012-08-02 18:54:41

+1

@TLP,我知道。但是,perl支持变量名称中的变量,我希望利用这个事实。我认为“这个”会很明显。 “a”不打印,而“b”是。我已经调整了问题。我完全有意用哈希来正确地完成它,并从一开始就做好准备。我希望看看能否实施并发现我认为是我不明白的奇怪行为。 – EricR 2012-08-02 19:19:02

请注意,此无关的事实,您使用的变量包含其他变量的名字:如果你想正确地做到这一点你是关闭使用哈希更好。

这不起作用的原因是因为${"var_a"}构造实际上是指包级变量$main::var_a

由于$var_a被声明为词法变量,因此它是一个不同的标识符,因此${"var_a"}是undef。

你可以看到,如果你改变my $var_aour $var_a

our $var_a="a"; 
my $var_b="b"; 
$var_c="c"; 

print ${"var_a"},"\n"; 
print ${"var_b"},"\n"; 
print ${"var_c"},"\n"; 

######## RESULTS: 
a 

c 

正如其他人所指出的,虽然是为什么你正在尝试做是不行的,你在做什么可能是一个很好的解释错误的方法。除非没有更好的方法,否则几乎不应该使用这种方法;没有你的问题,目前还不清楚更好的方法是什么,但最有可能的是像TLP的回答所说的那样。

+0

谢谢,这回答了技术问题。我并不是真的在寻找解决我的“问题”的方法,而是对行为的解释。 – EricR 2012-08-02 19:26:08

如果您想要符号引用,您希望使用散列。

my %user_vars = (var_a => 'what ever'); 
my $sub_a = 'a'; 
print $user_vars{"var_$sub_a"}; 


Output: 'what ever' 

使用符号引用用于此目的,因为他们没有必要,也有可能在你的问题的情况下是非常有害的。有关更多信息,请参阅Why it's stupid to 'use a variable as a variable name'?。几乎总是有一个更好的方法来做到这一点,一种方法是使sub_avar_a阵列,其中sub_avar_a的关键。这是很好的做法,当你不使用它们,以防止injection attacks始终锁定您的哈希值,例如:

use strict; 
use warnings; 
use Hash::Util qw(lock_hash unlock_hash); 

my @sub_a; 
my %var_a; 
lock_hash(%var_a); 

@sub_a = qw(a b c);   # the keys 

unlock_hash(%var_a); 
%var_a = (a => 'Value for a', b => 'Value for b', c => 'Value for c'); 
lock_hash(%var_a); 

print $var_a{$sub_a[0]};  # 'Value for a' 
print $var_a{'banana'};  # Fatal error when accessing data for banana. 
+0

您能否引用锁定哈希来防止注入攻击?干杯。 – EricR 2012-08-02 19:26:43

+0

如果可变哈希值接收到用户输入信息,这是我在大学时被告知的,那么在我的第一份工作中就会引起注入攻击,因此这就是我告诉其他人的信息。总是锁定哈希数组,并且只有在对正在计划添加的变量进行检查之后才解锁它们。我已经添加了关于如何引起注入攻击的参考链接。 – 2012-08-03 00:45:07

+1

抱歉,按键锁定无助于注射攻击。相反,您应该启用污点检查,请参阅[perldoc perlsec](http://p3rl.org/sec)。 – daxim 2012-08-03 00:52:01

使用字符串作为参考违反strict编译,你应该总是使用。

use strict; 
use warnings; 

my %hash; 

$hash{"var_a"} = "a"; 
print $hash{"var_a"},"\n";