如何修复 perl eval() 中的"找到裸词"问题



下面的代码返回"Bareword found where operator expected at (eval 1) line 1, near "*,out"(输出前缺少操作符?)">

$val = 0;
$name = "abc";
$myStr = '$val = ($name =~ in.*,out [)';
eval($myStr);

根据我的理解,我可以解决这个问题,通过包装"in。*,[";用'//'s阻塞。

但是那个"in。*,[";可以是多种多样的。(例如:用户输入)。用户可能会错过给出"//"。因此,还有其他的方法来处理这个问题吗?(例如:返回0如果eval()试图返回'Bareword found where…')

(string) eval的魔力和危险在于它将一堆虚拟字符转换成代码,编译并运行它。那么可以使用'$x = ,hi'吗?不,当然,当这个字符串被认为是代码时那是一个松散的逗号操作符,一个语法错误;还有一个"裸词"hi.字符串必须产生有效代码

在字符串eval中,首先解析表达式的值(它本身是在标量上下文中确定的),如果没有错误,则在当前Perl程序的词法上下文中作为块执行。

因此,问题中的字符串就像它所代表的那样,将只是(严重)无效的代码,无法编译,句号。如果字符串的in.*,out [部分在某种引号中,那么这是合法的,=~操作符将把它作为一个模式,并且您有一个正则表达式。当然,为什么不使用正则表达式的常规模式分隔符,如//(或m{}等)。

不管这个字符串以什么方式被获取它都会在一个变量中,不是吗?因此,您可以在eval中设置/$input/,并预先填充$input

但是,最重要的是,你确定没有别的办法吗?总会有的。字符串-eval是复杂和棘手的,很难使用,几乎不可能对齐-和危险。它运行任意的代码!即使没有恶意,也会把事情搞砸。

我强烈建议考虑其他解决方案。此外,还不清楚为什么首先需要eval—因为您只需要正则表达式模式作为用户输入(而不是代码),因此可以在正常代码中使用正则表达式,并在变量中使用模式,该模式在提供用户输入时提前填充。(注意,从用户那里获取模式也可能导致麻烦。)


如果你喜欢warnings,这是个问题,我们都喜欢。

以下是无效的Perl代码:

$val = ($name =~ in.*,out [)

您需要以下内容:

$val = $name =~ /in.*,out [/

(父母没有伤害,但也没有帮助。)

如果模式是用户提供的,可以使用以下命令:

$val = $name =~ /$pattern/

(不需要eval EXPR!)

从更正中注意到问题中的模式是不正确的。您可以使用eval BLOCK

捕获此类错误
eval { $val = $name =~ /$pattern/ };
die("Bad pattern "$pattern" provided: $@") if $@;

关于用户提供模式的注意:上面的模式不会让用户执行任意代码,但它不会保护您免受模式的影响,这些模式比宇宙的生命周期还长。

最新更新