2012-08-02 153 views
4
#!/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

回答

7

請注意,此無關的事實,您使用的變量包含其他變量的名字:如果你想正確地做到這一點你是關閉使用哈希更好。

這不起作用的原因是因爲${"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

3

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

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

0

使用字符串作爲參考違反strict編譯,你應該總是使用。

use strict; 
use warnings; 

my %hash; 

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