Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

perl variable substitution in variable name

Tags:

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

Why is b printed, but not a? This seems like very unexpected behaviour to me.

I'm trying to use a variable with a substituted name. In practice, I cannot just not declare the variable, since the assignment is being done in a forloop and thus has different lexical scope.

like image 320
EricR Avatar asked Aug 02 '12 18:08

EricR


People also ask

How do I assign a variable to another variable in Perl?

In an <EQN> or <eqn> tag, include an assignment statement like the following: $ variable = value ; where variable is the variable name and value is the value to be assigned.

What is $_ in Perl?

The most commonly used special variable is $_, which contains the default input and pattern-searching string. For example, in the following lines − #!/usr/bin/perl foreach ('hickory','dickory','doc') { print $_; print "\n"; }

What is @variable name in Perl?

A Perl variable name starts with either $ , @ or % followed by zero or more letters, underscores, and digits. Perl supports 3 kinds of variables: Scalars contain a single string or numeric value. The variable name must start with a $ . Arrays contain a randomly accessed ordered set of values.

What does @_ mean in Perl?

@ is used for an array. In a subroutine or when you call a function in Perl, you may pass the parameter list. In that case, @_ is can be used to pass the parameter list to the function: sub Average{ # Get total number of arguments passed. $ n = scalar(@_); $sum = 0; foreach $item (@_){ # foreach is like for loop...


2 Answers

Please note that this has NOTHING to do with the fact that you are using variables to contain the name of other variable.

The reason this doesn't work is because ${"var_a"} construct in reality refers to a package level variable $main::var_a.

Since $var_a is declared as a lexical variable, it's a DIFFERENT identifyer, and therefore ${"var_a"} is undef.

You can see that if you change my $var_a to our $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

As others noted, while there is a good explanation for why what you are trying to do doesn't work, WHAT you are doing is likely the wrong approach. You should almost NEVER use this method unless there's no better way; without your problem it's not clear what the better way is but most likely would be a hash like TLP's answer says.

like image 85
DVK Avatar answered Sep 17 '22 23:09

DVK


If you want a symbolic reference, you want to use a hash.

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


Output: 'what ever'

Do not use symbolic references for this purpose because they are unnecessary and likely very harmful in the context of your question. For more information, see Why it's stupid to 'use a variable as a variable name'?. There is almost always a better way to do this, one way is to make sub_a and var_a arrays, where sub_a is the key for var_a. It is good practice to always lock your hashes when you are not using them to prevent injection attacks, for example:

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.
like image 40
Branden S. Smith Avatar answered Sep 19 '22 23:09

Branden S. Smith