114

我一直在使用R CMD BATCH my_script.R终端来执行R脚本。我现在想将参数传递给命令,但是在使其正常工作时遇到了一些问题。如果我这样做,R CMD BATCH my_script.R blablablabla成为输出文件,而不是被解释为正在执行的 R 脚本可用的参数。

我已经尝试过Rscript my_script.R blabla似乎可以blabla正确地作为参数传递,但是我没有得到我得到的my_script.Rout输出文件R CMD BATCH(我想要这个.Rout文件)。虽然我可以将调用的输出重定向到Rscript我选择的文件名,但我不会像在文件中那样获得包含在文件中的 R 输入R CMD BATCH命令.Rout

因此,理想情况下,我正在寻求一种将参数传递给通过该方法执行的 R 脚本的方法,尽管如果有一种方法可以使其生成可比较的文件R CMD BATCH,我会很高兴使用这种方法。Rscript.Rout

4

6 回答 6

125

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

编辑:

不是我推荐它,而是......使用 and 的组合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
于 2013-01-05T01:04:58.357 回答
29

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

我把他的代码放在这里:

从命令行

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

测试.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)

在测试中

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

感谢森林人

于 2013-11-26T12:41:42.877 回答
11

您需要在参数之前放置参数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.
于 2013-01-05T00:42:05.230 回答
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 
于 2013-04-05T13:15:10.047 回答
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"
于 2016-03-16T09:52:48.017 回答
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)))
于 2016-12-15T00:50:31.133 回答