使用brew/whisker进行错误安全的模板化

bap*_*ste 7 templates r

外部程序需要一个带有一些控制参数的输入文件,我希望使用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,但我在其帮助页面中无法理解一件事.

我欢迎就更普遍的问题提出其他建议.

Mat*_*rde 4

使用正则表达式从模板中检索变量名称,您可以在渲染之前进行验证,例如,

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)