下面的代码返回"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 $@;
关于用户提供模式的注意:上面的模式不会让用户执行任意代码,但它不会保护您免受模式的影响,这些模式比宇宙的生命周期还长。