评估以字符串形式给出的表达式

问题描述 投票:247回答:6

我很想知道R是否可以使用它的eval()函数来执行例如由一个字符串。

这是一个常见的情况:

eval("5+5")

但是,而不是10我得到:

[1] "5+5"

有解决方案吗

r eval r-faq
6个回答
371
投票

eval()函数计算表达式,但"5+5"是一个字符串,而不是表达式。使用parse()text=<string>将字符串更改为表达式:

> eval(parse(text="5+5"))
[1] 10
> class("5+5")
[1] "character"
> class(parse(text="5+5"))
[1] "expression"

调用eval()会调用许多行为,有些行为不是很明显:

> class(eval(parse(text="5+5")))
[1] "numeric"
> class(eval(parse(text="gray")))
[1] "function"
> class(eval(parse(text="blue")))
Error in eval(expr, envir, enclos) : object 'blue' not found

另见tryCatch


88
投票

您可以使用parse()函数将字符转换为表达式。您需要指定输入是文本,因为默认情况下parse需要一个文件:

eval(parse(text="5+5"))

40
投票

抱歉,但我不明白为什么有太多人甚至认为字符串是可以评估的东西。你必须改变你的心态。忘记一边的字符串和表达式,调用,另一边的评估之间的所有连接。

(可能)唯一的连接是通过parse(text = ....),所有优秀的R程序员应该知道这很少是构造表达式(或调用)的有效或安全的方法。而是更多地了解substitute()quote(),以及可能使用do.call(substitute, ......)的力量。

fortunes::fortune("answer is parse")
# If the answer is parse() you should usually rethink the question.
#    -- Thomas Lumley
#       R-help (February 2005)

Dec.2017:好的,这是一个例子(在评论中,没有很好的格式):

q5 <- quote(5+5)
str(q5)
# language 5 + 5

e5 <- expression(5+5)
str(e5)
# expression(5 + 5)

如果你有更多的经验你会得知q5"call"e5"expression",甚至e5[[1]]q5相同:

identical(q5, e5[[1]])
# [1] TRUE

16
投票

或者,您可以使用evals包中的pander来捕获输出以及所有警告,错误和其他消息以及原始结果:

> pander::evals("5+5")
[[1]]
$src
[1] "5 + 5"

$result
[1] 10

$output
[1] "[1] 10"

$type
[1] "numeric"

$msg
$msg$messages
NULL

$msg$warnings
NULL

$msg$errors
NULL


$stdout
NULL

attr(,"class")
[1] "evals"

11
投票

现在你也可以使用lazy_eval包中的lazyeval函数。

> lazyeval::lazy_eval("5+5")
[1] 10

1
投票

同样使用rlang

eval(parse_expr("5+5"))
© www.soinside.com 2019 - 2024. All rights reserved.