将命令行参数传递给R CMD BATCH


102

我一直在R CMD BATCH my_script.R从终端执行R脚本。现在,我想将参数传递给命令,但是在使它运行时遇到了一些问题。如果我愿意,R CMD BATCH my_script.R blabla那么blabla它将成为输出文件,而不是被解释为正在执行的R脚本可用的参数。

我尝试过Rscript my_script.R blabla它似乎可以blabla正确地作为参数传递,但是后来我没有得到所得到的my_script.Rout输出文件R CMD BATCH(我想要该.Rout文件)。虽然我可以调用的输出重定向到Rscript我的选择的文件名,我就不会得到列入方式文件中的R输入命令R CMD BATCH是否在.Rout文件中。

因此,理想情况下,我正在寻找一种将参数传递给通过该R CMD BATCH方法执行的R脚本的方法,尽管我对使用Rscript一种能够使它产生可比.Rout文件的方法感到满意。

Answers:


114

我的印象是R CMD BATCH有点遗物。在任何情况下,最新的Rscript可执行文件(在所有平台上都可用)以及commandArgs()使命令行参数的处理变得非常容易。

例如,这是一个小脚本-称它为"myScript.R"

## myScript.R
args <- commandArgs(trailingOnly = TRUE)
rnorm(n=as.numeric(args[1]), mean=as.numeric(args[2]))

这是从命令行调用它的样子

> Rscript myScript.R 5 100
[1]  98.46435 100.04626  99.44937  98.52910 100.78853

编辑:

并非我不建议这样做,而是...使用source()and 的组合sink(),您可以Rscript生成一个.Rout类似的文件R CMD BATCH。一种方法是创建一个小的R脚本(称为 RscriptEcho.R),您可以直接使用Rscript进行调用。它可能看起来像这样:

## RscriptEcho.R
args <- commandArgs(TRUE)
srcFile <- args[1]
outFile <- paste0(make.names(date()), ".Rout")
args <- args[-1]

sink(outFile, split = TRUE)
source(srcFile, echo = TRUE)

要执行您的实际脚本,您需要执行以下操作:

Rscript RscriptEcho.R myScript.R 5 100
[1]  98.46435 100.04626  99.44937  98.52910 100.78853

它将myScript.R使用提供的参数执行,并将交错的输入,输出和消息接收到唯一命名的.Rout

Edit2:
您可以详细运行Rscript并将详细输出放置在文件中。

Rscript --verbose myScript.R 5 100 > myScript.Rout

4
我也得到的印象R CMD BATCH是遗物。我喜欢它的地方是,它生成的.Rout文件不仅包含脚本输出,而且还交织.R产生该输出的脚本文件中的输入命令/注释。
布莱斯·托马斯

1
我听到你了 那是(我想仍然是!)的一个不错的方面R CMD BATCH
乔什·奥布莱恩

5
但我认为你可以做得比更好R CMD BATCHknitr,例如,Rscript -e "knitr::stitch(commandArgs(TRUE)[1])" my_script.R(你可以替换stitch使用stitch_rhtml或者stitch_rmd,你需要安装knitrGithub上,因为我刚刚发现了一个bug中stitch...)
艺辉谢

7
只需添加我的0.02,从终端使用重定向也很容易。一个示例是Rscript myfile.R > path/to/mylog.Rout文件输出保存在.Rout文件中,而不是打印到stdout(屏幕)。
詹姆斯·普林格

4
要添加到@JamesPringle,我通常希望将输出同时打印在屏幕上(以实时监视)和文件(以稍后查看)中。我愿意Rscript myfile.R | tee mylog.Rout
Heisenberg 2015年

26

在尝试了这里描述的选项之后,我在r-bloggers中的Forester中找到了这篇文章。我认为这是一个干净的选择。

我把他的代码放在这里:

从命令行

$ R CMD BATCH --no-save --no-restore '--args a=1 b=c(2,5,6)' test.R test.out &

测试

##First read in the arguments listed at the command line
args=(commandArgs(TRUE))

##args is now a list of character vectors
## First check to see if arguments are passed.
## Then cycle through each element of the list and evaluate the expressions.
if(length(args)==0){
    print("No arguments supplied.")
    ##supply default values
    a = 1
    b = c(1,1,1)
}else{
    for(i in 1:length(args)){
      eval(parse(text=args[[i]]))
    }
}

print(a*2)
print(b*3)

在测试中

> print(a*2)
[1] 2
> print(b*3)
[1]  6 15 18

感谢森林人


需要注意的重要一点是,如果参数为字符类型,则无需使用单引号/双引号。例如:R CMD BATCH'--args a = FolderName'test.R test.out&
d2a2d

正如Forester帖子中提到的那样,这--args是关键。它还可以与R --no-save --no-restore --args a=1 < test.RR --no-save --no-restore < test.R --args a=1
戴夫

有没有办法将参数从命令行传递到--args?假设我们要在命令行中执行一个for循环,然后在--args行中发送它。
user2809432 '19

9

在您的R脚本中,名为test.R

args <- commandArgs(trailingOnly = F)
myargument <- args[length(args)]
myargument <- sub("-","",myargument)
print(myargument)
q(save="no")

从命令行运行:

R CMD BATCH -4 test.R

您的输出文件test.Rout将显示参数4已成功传递给R:

cat test.Rout

> args <- commandArgs(trailingOnly = F)
> myargument <- args[length(args)]
> myargument <- sub("-","",myargument)
> print(myargument)
[1] "4"
> q(save="no")
> proc.time()
user  system elapsed 
0.222   0.022   0.236 

8

您需要将参数放在前面my_script.R-在参数上使用,例如

R CMD BATCH -blabla my_script.R

commandArgs()-blabla在这种情况下将作为字符串接收。有关详细信息,请参见帮助:

$ R CMD BATCH --help
Usage: R CMD BATCH [options] infile [outfile]

Run R non-interactively with input from infile and place output (stdout
and stderr) to another file.  If not given, the name of the output file
is the one of the input file, with a possible '.R' extension stripped,
and '.Rout' appended.

Options:
  -h, --help        print short help message and exit
  -v, --version     print version info and exit
  --no-timing           do not report the timings
  --            end processing of options

Further arguments starting with a '-' are considered as options as long
as '--' was not encountered, and are passed on to the R process, which
by default is started with '--restore --save --no-readline'.
See also help('BATCH') inside R.

2
我发现,如果我做这种方式,并在脚本中使用args <- commandArgs(FALSE),然后打印指定参数时,我结束了所有的参数,包括那些不是我的,喜欢--restore--save如果我用,等commandArgs(TRUE)我都拿不出论据。有没有办法得到我自己的其他论点? --args看起来很有前途,但我无法使其正常工作...
Bryce Thomas

您必须从头算起参数(例如size-2,size-1,size)-您的参数将始终位于末尾。
ynka 2014年

4

我添加一个答案是因为我认为单行解决方案总是好的!在myRscript.R文件顶部,添加以下行:

eval(parse(text=paste(commandArgs(trailingOnly = TRUE), collapse=";")))

然后使用以下内容提交脚本:

R CMD BATCH [options] '--args arguments you want to supply' myRscript.R &

例如:

R CMD BATCH --vanilla '--args N=1 l=list(a=2, b="test") name="aname"' myscript.R &

然后:

> ls()
[1] "N"    "l"    "name"

0

这是使用处理命令行参数的另一种方法R CMD BATCH。我的方法基于此处的早期答案,可让您在命令行中指定参数,并在R脚本中提供部分或全部默认值。

这是一个R文件,我将其命名为test.R

defaults <- list(a=1, b=c(1,1,1)) ## default values of any arguments we might pass

## parse each command arg, loading it into global environment
for (arg in commandArgs(TRUE))
  eval(parse(text=arg))

## if any variable named in defaults doesn't exist, then create it
## with value from defaults
for (nm in names(defaults))
  assign(nm, mget(nm, ifnotfound=list(defaults[[nm]]))[[1]])

print(a)
print(b)

在命令行中,如果我键入

R CMD BATCH --no-save --no-restore '--args a=2 b=c(2,5,6)' test.R

那么在R中我们将有a= 2b=c(2,5,6)。但是我可以说省略b,并添加另一个参数c

R CMD BATCH --no-save --no-restore '--args a=2 c="hello"' test.R

然后在R中我们有a=2b= c(1,1,1)(默认值)和c="hello"

最后,为了方便起见,我们可以将R代码包装在一个函数中,只要我们注意环境即可:

## defaults should be either NULL or a named list
parseCommandArgs <- function(defaults=NULL, envir=globalenv()) {
  for (arg in commandArgs(TRUE))
    eval(parse(text=arg), envir=envir)

  for (nm in names(defaults))
    assign(nm, mget(nm, ifnotfound=list(defaults[[nm]]), envir=envir)[[1]], pos=envir)
}

## example usage:
parseCommandArgs(list(a=1, b=c(1,1,1)))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.