计算以字符串形式给出的表达式
我很好奇 R 是否可以使用其 eval()
函数来执行由字符串等提供的计算。
这是一个常见的情况:
eval("5+5")
但是,我得到的不是 10,而是:
[1] "5+5"
有解决方案吗?
I'm curious to know if R can use its eval()
function to perform calculations provided by e.g. a string.
This is a common case:
eval("5+5")
However, instead of 10 I get:
[1] "5+5"
Any solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
eval()
函数计算表达式的值,但"5+5"
是字符串,而不是表达式。使用parse()
和text=
将字符串更改为表达式:调用
eval()
会调用许多行为,其中一些是不是很明显:另请参阅 tryCatch。
The
eval()
function evaluates an expression, but"5+5"
is a string, not an expression. Useparse()
withtext=<string>
to change the string into an expression:Calling
eval()
invokes many behaviours, some are not immediately obvious:See also tryCatch.
您可以使用
parse()
函数将字符转换为表达式。您需要指定输入是文本,因为解析默认需要一个文件:You can use the
parse()
function to convert the characters into an expression. You need to specify that the input is text, because parse expects a file by default:抱歉,但我不明白为什么太多人甚至认为字符串是可以评估的东西。你必须改变你的心态,真的。
忘记一侧的字符串与另一侧的表达式、调用、评估之间的所有连接。
(可能)唯一的连接是通过parse(text = ....),所有优秀的 R 程序员都应该知道,这很少是构造表达式(或调用)的有效或安全的方法。而是了解有关
substitute()
、quote()
的更多信息,以及可能使用do.call(substitute, ......)
的强大功能代码>.2017 年 12 月:好的,这是一个示例(在注释中,没有很好的格式):
如果您更有经验,您会了解到
q5
是一个“call”
而e5
是一个“表达式”
,甚至e5[[1]]
与q5
相同:Sorry but I don't understand why too many people even think a string was something that could be evaluated. You must change your mindset, really.
Forget all connections between strings on one side and expressions, calls, evaluation on the other side.
The (possibly) only connection is via
parse(text = ....)
and all good R programmers should know that this is rarely an efficient or safe means to construct expressions (or calls). Rather learn more aboutsubstitute()
,quote()
, and possibly the power of usingdo.call(substitute, ......)
.Dec.2017: Ok, here is an example (in comments, there's no nice formatting):
and if you get more experienced you'll learn that
q5
is a"call"
wherease5
is an"expression"
, and even thate5[[1]]
is identical toq5
:不知道为什么没有人专门提到两个 Base R 函数来执行此操作:str2lang() 和 str2expression()。这些是
parse()
的变体,但似乎更干净地返回表达式:还想反驳海报说任何试图这样做的人都是错误的。我正在读取作为文本存储在文件中的 R 表达式,并尝试对它们求值。这些功能非常适合此用例。
Not sure why no one has mentioned two Base R functions specifically to do this:
str2lang()
andstr2expression()
. These are variants ofparse()
, but seem to return the expression more cleanly:Also want to push back against the posters saying that anyone trying to do this is wrong. I'm reading in R expressions stored as text in a file and trying to evaluate them. These functions are perfect for this use case.
现在,您还可以使用
lazyeval
包中的lazy_eval
函数。Nowadays you can also use
lazy_eval
function fromlazyeval
package.或者,您可以使用我的
pander
包中的evals
来捕获输出以及所有警告、错误和其他消息以及原始结果:Alternatively, you can use
evals
from mypander
package to capture output and all warnings, errors and other messages along with the raw results:类似地使用 rlang:
Similarly using
rlang
:我同意 eval 和 parse 存在一些问题,但如果表达式位于字符串中,则似乎无能为力。 tidyverse 专家也在glue 包中使用了此 eval 解析,请参阅 https://github.com/tidyverse/glue/blob/d47d6c7701f738f8647b951df418cfd5e6a7bf76/R/transformer.R#L1-L12
也许是
eval(parse(text="5+ 5"))
如果文本字符串来自不受信任的来源,则存在安全问题,例如想象user_input = "list.files()"
或更糟的 file.remove...一项潜在的工作周围是下面。
这个想法是设置要在其中计算表达式的 R 环境。在 R 中,“R 附带”的大多数函数实际上都在 R 启动时自动加载的包中,例如“list.files”、“library”和“attach”函数来自“base”包。通过将计算环境设置为空环境,这些函数将不再可供待计算的表达式使用,从而防止恶意代码的执行。在下面的代码中,默认情况下我仅包含算术相关的函数,否则用户可以为评估环境提供明确允许的函数。
I agree there are concerns around eval and parse, but if the expression is in a string, there appears nothing much that can be done. This eval parse is also used in the glue package by the tidyverse experts, see https://github.com/tidyverse/glue/blob/d47d6c7701f738f8647b951df418cfd5e6a7bf76/R/transformer.R#L1-L12
Perhaps the accepted answer of
eval(parse(text="5+5"))
has security concerns if the text string is from an untrusted source, eg imagineuser_input = "list.files()"
or worse file.remove...One potential work around is below.
The idea is to set the R environment in which the expression is to be evaluated. In R, most functions that 'comes with R' are actually in packages that gets autoloaded at R start up, eg 'list.files', 'library' and 'attach' functions come from the 'base' package. By setting the evaluation environment to empty environment, these functions are no longer available to the expression to be evaluated, preventing malicious code from executing. In the code below, by default I include only arithmetic related functions, otherwise user can provide the evaluation environment with explicitly allowed functions.