[英]List all the packages required in a script assuming package::function() in R
假设脚本中的所有非基础 R 函数都由package::function()
调用。 因此,它在脚本运行期间没有任何完整的包加载。 假设我们有一个名为run.R
的 R 脚本, run.R
包含以下内容。
"data.table::fread(file)"
在这个例子中,脚本需要data.table
包。 我正在寻找一个 R 函数,它读取这个外部run.R
脚本会给安装所有请求的包的代码,即:
install.packages("data.table")
关于现有功能或策略的任何想法?
您可以使用正则表达式尝试类似的操作:
f <- file("/path/to/here/file.R") # set up connection to file
file_lines <- readLines(con = f) # read file into list
close(f)
pckgs <- lapply(file_lines, function(l) {
if(grepl("::", l)){
gsub(".*?([[:alnum:]\\.]+)::.*","\\1", l)
} else {
return(NULL)
}
})
unique(unlist(pckgs))
我的工作假设包名只包含字母和数字。 如果不是这种情况,您可能需要更改正则表达式模式。
更新:将假设更改为包含.
根据data.table
示例
使用正则表达式的其他解决方案也将匹配::
如果它出现在注释或字符串文字中。 最好解析脚本并查找解析为pkg::fn
操作的内容。 例如:
src <- "data.table::fread(file)"
# Use src <- readLines("source.R") in the real case, or parse the file directly
parsed <- parse(text = src)
parseData <- getParseData(parsed)
parseData$text[parseData$token == "SYMBOL_PACKAGE"]
#> [1] "data.table"
编辑添加:您可以将其放入一个函数中,以便在运行脚本之前安装必要的软件包。 例如,如果这些行在~/temp/run.R
:
file <- "not::a::package"
data.table::fread(file)
foobar::notafunction()
然后你会得到这些结果:
installThenSource <- function(file, ...) {
parsed <- parse(file)
parseData <- getParseData(parsed)
packages <- unique(parseData$text[parseData$token == "SYMBOL_PACKAGE"])
for (p in packages) {
if (!requireNamespace(p, quietly = TRUE)) {
message("Installing ", p)
install.packages(p)
if (!requireNamespace(p, quietly = TRUE))
stop("Install of ", p, " failed.")
} else
message("Package ", p, " already installed.")
}
source(file, ...)
}
installThenSource("~/temp/run.R")
#> Package data.table already installed.
#> Installing foobar
#> Warning: package 'foobar' is not available (for R version 3.6.1)
#> Error in installThenSource("~/temp/run.R"): Install of foobar failed.
这是一个查找类似package::function
字符串的package::function
。
findPackages <- function(file){
txt <- readLines(file)
inx <- grep('::', txt)
txt <- txt[inx]
m <- regexpr('[[:alnum:]]+::', txt)
pkg <- regmatches(txt, m)
unique(sub('::', '', pkg))
}
这个 Ubuntu bash 命令获取工作目录中所有带有::
文件*.R
。
fls <- system2('grep', args = c('-l', '::', '*.R'), stdout = TRUE)
现在将该函数应用到一个调用类似函数的文件。
findPackages(fls[1])
以及使用 bash 命令找到的所有此类文件。
pkgs <- lapply(fls, findPackages)
unique(unlist(pkgs))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.