使用eval初始化perl变量

sda*_*aau 7 variables perl scope eval

我猜这对于那些了解Perl的人来说应该是显而易见的,但是我根本就没有得到它......我也猜测它与Perl范围内描述的问题有关«黑暗 - 但我不能在我的案例中应用任何问题.

无论如何,这是代码:

#!/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.
Run Code Online (Sandbox Code Playgroud)

简单来说,我希望有一些像" $varA = 1;"写成字符串(文本文件); 我想perleval它,这样后来我有机会获得变量" $varA在同一个脚本" -我得到的错误,当我试图访问这些后eval在上面的代码中的注释(但是,没有警告报告期间eval).(我猜,如果eval运行在与主脚本不同的上下文中,我需要的是"全局"变量?)

我该怎么做呢?我是否必须完成所有的包定义业务,即使是像上面这样的简单脚本?

非常感谢任何答案,
干杯!

mob*_*mob 14

它与范围有关.变量my在eval表达式中声明.这使它们成为eval语句的本地语句,并且在eval语句退出后无法访问.您可以先声明它们,但是:

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
Run Code Online (Sandbox Code Playgroud)

或者如你所知,你可以使用全局变量.最简单的(虽然不一定是"最好的"方式)是::在所有变量名前加上它们并将它们放在主包中.

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

eval $tvars;
print "A=$::varA, B=$::varB, C=$::varC\n";
Run Code Online (Sandbox Code Playgroud)

现在,当您our在示例中尝试变量时,实际上是在初始化包(全局)变量.但在eval声明之外,您仍需要限定(即指定包名称)以便访问它们:

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

print $main::foo;    # ==> 5
Run Code Online (Sandbox Code Playgroud)