Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializing Perl variables using eval

I'm guessing this should be something obvious to those knowing Perl, but I simply don't get it... I also guess it has to do with problems described in Perl scoping « darkness - but I cannot apply any of that in my case.

Anyway, here's the code:

#!/usr/bin/env perl
# call with:
# ./test.pl

use strict;

my $tvars = "my \$varA = 1;
my \$varB = 2;
my \$varC = 3;
";

my @lines = split /\n/, $tvars;
foreach my $line (@lines) {
  print "$line\n";
  eval $line; warn $@ if $@;
}

#~ print "$varA\n"; # Global symbol "$varA" requires explicit package name at ./test.pl line 18.
#~ print "$varB\n"; # Global symbol "$varB" requires explicit package name at ./test.pl line 19.
#~ print "$varC\n"; # Global symbol "$varC" requires explicit package name at ./test.pl line 20.

$tvars = "our \$varA = 1;
our \$varB = 2;
our \$varC = 3;
";

@lines = split /\n/, $tvars;
foreach my $line (@lines) {
  print "$line\n";
  eval $line; warn $@ if $@;
}

print "$varA\n"; # Global symbol "$varA" requires explicit package name at ./test.pl line 33.
print "$varB\n"; # Global symbol "$varB" requires explicit package name at ./test.pl line 34.
print "$varC\n"; # Global symbol "$varC" requires explicit package name at ./test.pl line 35.

Simply speaking, I'd like to have something like "$varA = 1;" written as a string (text file); and I'd like perl to eval it, so that afterwards I have access to variable "$varA" in the same script - the errors I get when I try to access those after an eval are in the comments of the code above (however, no warnings are reported during the eval). (I'm guessing, what I'd need is something like "global" variables, if the eval runs in a different context than the main script?)

How would I go about doing that? Do I have to go through all of that package definition business, even for a simple script like the above?

like image 858
sdaau Avatar asked Sep 21 '11 21:09

sdaau


People also ask

How do I initialize a variable in Perl?

Creating Variables The declaration happens automatically when you assign a value to a variable. The equal sign (=) is used to assign values to variables. Keep a note that this is mandatory to declare a variable before we use it if we use use strict statement in our program.

What does eval command do in Perl?

The eval function takes a character string, and evaluates it in the current perl environment, as if the character string were a line in the currently executing perl program.

What does eval return in Perl?

In both forms, the value returned is the value of the last expression evaluated inside the mini-program; a return statement may also be used, just as with subroutines. The expression providing the return value is evaluated in void, scalar, or list context, depending on the context of the eval itself.

What is $var in Perl?

Array VariablesThe dollar sign ($) is used to refer a single element of an array with the variable name followed by the index of the element in square brackets. Here is an example of how to use an array variable: Perl.


1 Answers

It has everything to do with scoping. The variables are declared with my inside the eval expression. This makes them local to the eval statement and not accessible once the eval statement exits. You can declare them first, though:

my ($varA, $varB, $varC);  # declare outside the eval statement

my $tvars = "\$varA = 1;
\$varB = 2;
\$varC = 3;
";

eval $tvars;
# local $varA, $varB, $varC variables are now initialized

or as you suggest, you can use global variables. The easiest (though not necessarily the "best" way) is to prepend :: to all variable names and get them in the main package.

my $tvars = "\$::varA = 1;
\$::varB = 2;
\$::varC = 3;
";

eval $tvars;
print "A=$::varA, B=$::varB, C=$::varC\n";

Now when you tried our variables in your example, you actually were initializing package (global) variables. But outside the eval statement, you still need to qualify (i.e., specify the package name) them in order to access them:

$tvar = "our \$foo = 5";
eval $tvar;

print $main::foo;    # ==> 5
like image 96
mob Avatar answered Sep 27 '22 17:09

mob