外部程序需要一个带有一些控制参数的输入文件,我希望使用R自动生成它们.通常,我只是paste("parameter1: ", param1, ...)用来创建长文本字符串并输出到文件,但脚本很快变得不可读.这个问题可能非常适合胡须,
library(whisker)
template= 'Hello {{name}}
You have just won ${{value}}!
'
data <- list( name = "Chris", value= 124)
whisker.render(template, data)
Run Code Online (Sandbox Code Playgroud)
我的问题是,没有安全检查data包含所有必需的变量,例如
whisker.render(template, data[-1])
Run Code Online (Sandbox Code Playgroud)
我会默默地忽略我忘记指定名字的事实.但是,如果我无法生成完整的配置文件,我的终端程序将崩溃.
另一个模板系统由brew; 它具有实际评估事物的优势,并且可能还有助于检测缺失的变量,
library(brew)
template2 = 'Hello <%= name %>
You have just won $<%= value %>!
'
data <- list( name = "Chris", value= 124)
own_brew <- function(template, values){
attach(values, pos=2)
out = capture.output(brew(text = template))
detach(values, pos=2)
cat(out, sep='\n')
invisible(out)
}
own_brew(template2, data)
own_brew(template2, data[-1]) # error
Run Code Online (Sandbox Code Playgroud)
但是,我遇到两个问题:
attach() ... detach()不理想,(偶尔发出警告),或者至少我不知道如何正确使用它.我试图为其定义一个环境brew(),但是它过于严格,不再了解base功能......
即使发生错误,函数仍会返回一个字符串.我试着打电话try()但我没有错误处理的经验.如何告诉它退出不产生输出的功能?
编辑:我已更新brew解决方案以使用新环境而不是attach(),并在出现错误时停止执行.(?capture.output建议在这里使用它不是正确的功能,因为"如果在评估表达式时出现错误,则尝试尽可能地将输出写入文件"...)
own_brew <- function(template, values, file=""){
env <- as.environment(values)
parent.env(env) <- .GlobalEnv
a <- textConnection("cout", "w")
out <- try(brew(text = template, envir=env, output=a))
if(inherits(out, "try-error")){
close(a)
stop()
}
cat(cout, file=file, sep="\n")
close(a)
invisible(cout)
}
Run Code Online (Sandbox Code Playgroud)
必须有一个更简单的方法tryCatch,但我在其帮助页面中无法理解一件事.
我欢迎就更普遍的问题提出其他建议.
使用正则表达式从模板中检索变量名称,您可以在渲染之前进行验证,例如,
render <- function(template, data) {
vars <- unlist(regmatches(template, gregexpr('(?<=\\{\\{)[[:alnum:]_.]+(?=\\}\\})', template, perl=TRUE)))
stopifnot(all(vars %in% names(data)))
whisker.render(template, data)
}
render(template, data)
Run Code Online (Sandbox Code Playgroud)