如何使用 R 函数将包含注释的代码写入文件?

How can I write code containing comments to a file, using an R function?

我正在尝试从 R 中编写一个 Rscript。单独使用 quote()$wholeSrcref 属性效果很好。但是,在函数中使用时会写入额外的不需要的行。详情如下。

我的第一次尝试是 quote() 表达式,然后将引用的表达式写入文件,即

expr <- quote({
  a <- 1 # comment 1
  b <- 2 # comment 2
})
writeLines(tail(as.character(expr), -1), file)

但是,代码中的注释不会写入文件。解决方法是使用 $wholeSrcref 属性,如 所示。我的第二次尝试:

library(magrittr)
expr <- quote({
  a <- 1 # comment 1
  b <- 2 # comment 2
})
attributes(expr)$wholeSrcref %>% as.character() %>%
  tail(-1) %>%  # remove '{'
  head(-1) %>%  # remove '}'
writeLines(file)

这很好用。但是,当将 this 包装在一个函数中时,函数体的一部分也会被添加到引用表达式的前面。也就是说,给定以下代码,

library(magrittr)
f <- function(dir) {
  # change directory to dir
  # do stuff

  expr <- quote({
    a <- 1 # comment 1
    b <- 2 # comment 2
  })

  attributes(expr)$wholeSrcref %>% as.character() %>%
    tail(-1) %>%  # remove '{'
    head(-1) %>%  # remove '}'
  writeLines(file)

  # do more stuff
}
f(dir="")

文件将包含

  # change directory to dir 
  # do stuff 

  expr <- quote({
    a <- 1 # comment 1
    b <- 2 # comment 2

如何只将引用的表达式写入文件?

嗯,最简单的方法是计算 quote 函数上方的行数并调整 tail 函数以排除这些行。诚然,它不是很优雅

f <- function(dir) {
  # change directory to dir
  # do stuff
  
  expr <- quote({
    a <- 1 # comment 1
    b <- 2 # comment 2
  })
  exclusion_line <- which(grepl("expr <- quote({",
                               attributes(expr)$wholeSrcref %>% as.character(),
                               fixed = TRUE))
  attributes(expr)$wholeSrcref %>% as.character() %>%
    tail(-exclusion_line) %>%  # remove '{'
    head(-1) %>%  # remove '}'
    writeLines(file)
  
  # do more stuff
}
f(dir="")

正如用户 starja 在他的 中指出的那样,解决这个问题的一种方法是找到引用表达式的开头。在问题给出的示例中,可以搜索 "expr <- quote({",如:

  expr_ref <- attributes(expr)$wholeSrcref %>% as.character()
  exclusion_line <- grep("expr <- quote({", 
                         expr_ref, fixed = TRUE) 

  expr_ref %>%
    tail(-exclusion_line) %>%  # remove up till '{'
    head(-1) %>%  # remove '}'
    writeLines(file)

一个警告是硬编码 "expr <- quote({"。如果我们想使用 "expr" 以外的另一个变量名怎么办?我们将上面的代码放在一个函数中,修改为deparse(substitute(...)),即

write_expr <- function(expr, file) {

  expr_name <- deparse(substitute(expr))
  expr_ref <- attr(expr, "wholeSrcref") %>% as.character()
  exclusion_line <- grep(paste0("^\s*", expr_name, "\s*<-"), expr_ref)

 expr_ref %>%
    tail(-exclusion_line) %>%  # remove up till '{'
    head(-1) %>%  # remove '}'
    writeLines(file)
}

并将f修改为

f <- function(dir) {
  # change directory to dir
  # do stuff
  
  some_expr <- quote({
    a <- 1 # comment 1
    b <- 2 # comment 2
  })
  write_expr(some_expr, file)

  # do more stuff
}

现在,调用 f() 后,文件包含

    a <- 1 # comment 1
    b <- 2 # comment 2

随心所欲。