Initializing perl variables using eval

匿名 (未验证) 提交于 2019-12-03 02:20:02

问题:

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 - but I cannot apply any of that in my case.

Anyways, 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?

Many thanks in advance for any answers,
Cheers!

回答1:

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


回答2:

The problem is that when you do eval $string, $string is evaluated as its own subroutine which has its own lexical scope. From perldoc -f eval:

In the first form [in which the argument is a string], the return value of EXPR is parsed and  executed as if it were a little Perl program. The value of the expression (which is itself  determined within scalar context) is first parsed, and if there were no errors, executed in the  lexical context of the current Perl program, so that any variable settings or subroutine and format  definitions remain afterwards.

So, in other words, if you have:

use strict; use warnings; eval "my $foo=5;"; print "$foo\n";

you'll get an error:

Global symbol "$foo" requires explicit package name at -e line 3. Global symbol "$foo" requires explicit package name at -e line 4.

However, if you initialize your variables first, you're fine.

use strict; use warnings; my $foo; eval "\$foo=5;"; print "$foo\n"; #prints out 5, as expected.


回答3:

jjolla, you can use require $filename; or require "filename"; to include a file that has perl syntax. this would declare any variables you need as globals. But as always, be careful with Globals.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!