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

问题描述 投票:88回答:6

我一直在使用终端上的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 CMD BATCH.Rout文件中那样获取文件中包含的R输入命令。

因此,理想情况下,我正在尝试将参数传递给通过R CMD BATCH方法执行的R脚本,但如果有办法使其生成类似的Rscript文件,则会对使用.Rout的方法感到满意。

r rscript
6个回答
96
投票

我的印象是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()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

23
投票

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

我把他的代码放在这里:

从命令行

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

Test.R

##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)

在test.out中

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

感谢Forester


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.

3
投票

我添加了一个答案,因为我认为一线解决方案总是好的!在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处理命令行参数的另一种方法。我的方法基于an earlier answer here,允许您在命令行中指定参数,并在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)))
© www.soinside.com 2019 - 2024. All rights reserved.