代码:
my $tmp='x $i y'; # define a macro or whatever
for my $i (0..5){
my $var;
# eval { $var=$tmp; }; # A
# eval { $var="x $i y"; }; # B
$var="x $i y"; # C
print $var."\n";
}
B和C会打印
x 0 y
x 1 y
x 2 y
打印
x $i y
x $i y
x $i y
A有什么问题?
答案 0 :(得分:2)
如果您评估$tmp
,它将只返回其中的字符串,这意味着您将执行:$var = 'x $i y'
。您需要在$tmp
中评估字符串,而不是$var
。此外,你不能直接评估字符串,你需要用双引号括起来,以允许插入$i
,如下所示:
$tmp = '"x $i y"'; # note double quotes inside
...
$var = eval $tmp;
然而,eval
对任何此类问题都是一种野蛮的解决方案。大多数时候你认为你需要它,你需要再考虑一下。您的解决方案可能是代码引用:
my $tmp = sub { my $num = shift; return "x $num y" };
for my $i (0 .. 5) {
print $tmp->($i);
}
在这里,您不会尝试在for循环中使用实际的$i
参数,而是将$i
作为参数传递给sub,后者使用它并返回字符串。
答案 1 :(得分:2)
eval BLOCK
仅捕获异常,因此与问题无关。所以这给我们留下了以下代码:
my $i;
my $tmp = 'x $i y';
$i = 3;
my $var = $tmp;
在两种情况下,赋值的右侧都是相同的字符串,那么为什么期望$tmp
和$var
最终得到不同的值?这毫无意义。
那么如何解决您的问题呢?如果您希望将$tmp
的内容用作Perl代码,则需要使用eval EXPR
,而$tmp
的内容实际上必须是Perl代码。
my $i;
my $tmp = '"x $i y"'; # Quotes added to make it valid Perl.
$i = 3;
my $var = eval $tmp; # eval EXPR instead of eval BLOCK.
但那是错的。您正在使用eval EXPR
作为模板系统。使用真实的tempalte系统,如Template-Toolkit。但是,如果您想继续使用x $i y
表单的模板,请查看String::Interpolate。
答案 2 :(得分:0)
双引号字符串中的变量名称被替换为值,单引号字符串中的变量不(称为interpolation)。这就是A
选项打印$i
而不是值的原因。
A
与:
my $var = 'x $i y';
print $var."\n"; # prints 'x $i y\n';
答案 3 :(得分:0)
对于初学者来说,当你将一个字符串放在单引号中时,它不会将你的变量解释为它们的值,而是你输入的文字字符串。
现在就“制作一个宏”来说,这就是你想要做的事情。这是一种在perl中执行此操作的方法,但老实说,您编写的代码永远不应该执行此类操作。
use strict;
# This is your "counter" variable
my $i = 0;
# This is your "Macro"
my $macro = sub{ return 'x ' . ${\$i} . ' y'};
for my $x (0..5){
$i = $x;
print &{$macro}, "\n";
}
结果是:
x 0 y
x 1 y
x 2 y
x 3 y
x 4 y
x 5 y