2010-01-27 127 views
257

我有一个R脚本,我希望能够提供几个命令行参数(而不是代码本身的硬编​​码参数值)。该脚本在Windows上运行。如何从R脚本读取命令行参数?

我找不到有关如何将命令行中提供的参数读入我的R脚本的信息。我会很惊讶,如果它不能完成,所以也许我只是没有使用我的谷歌搜索最好的关键字...

任何指针或建议?

+0

你需要设置rscript可执行文件的位置 – 2017-08-02 14:37:45

回答

189

Dirk's answer here是您需要的一切。这是一个最小可重现的例子。

我做了两个文件:exmpl.batexmpl.R

  • exmpl.bat

    set R_Script="C:\Program Files\R-3.0.2\bin\RScript.exe" 
    %R_Script% exmpl.R 2010-01-28 example 100 > exmpl.batch 2>&1 
    

    或者,使用Rterm.exe

    set R_TERM="C:\Program Files\R-3.0.2\bin\i386\Rterm.exe" 
    %R_TERM% --no-restore --no-save --args 2010-01-28 example 100 <exmpl.R> exmpl.batch 2>&1 
    
  • exmpl.R

    options(echo=TRUE) # if you want see commands in output file 
    args <- commandArgs(trailingOnly = TRUE) 
    print(args) 
    # trailingOnly=TRUE means that only your arguments are returned, check: 
    # print(commandArgs(trailingOnly=FALSE)) 
    
    start_date <- as.Date(args[1]) 
    name <- args[2] 
    n <- as.integer(args[3]) 
    rm(args) 
    
    # Some computations: 
    x <- rnorm(n) 
    png(paste(name,".png",sep="")) 
    plot(start_date+(1L:n), x) 
    dev.off() 
    
    summary(x) 
    

将这两个文件保存在同一个目录中并开始exmpl.bat。在结果你会得到:

  • example.png一些情节
  • exmpl.batch与所有做

您还可以添加变量的环境%R_Script%

"C:\Program Files\R-3.0.2\bin\RScript.exe" 

和在批处理脚本中使用它作为%R_Script% <filename.r> <arguments>

RScriptRterm之间的差异:

8

你需要littler(发音为 '小R')

德克将在约15分钟的阐述;)

+23

我迟到了七分钟。 Intertubes上的流量肯定不好。 – 2010-01-28 01:12:04

+2

要么你或你变老。 ;) – 2010-01-28 15:15:19

+2

我显然没有读好他的问题。 -1,因为我没有看到Windows需求 – 2010-01-28 15:16:37

114

的几点:

  1. 命令行参数 可通过commandArgs()访问,因此 请参阅help(commandArgs)以获取 概述。

  2. 您可以在所有平台(包括Windows)上使用Rscript.exe。它将支持commandArgs()littler可以移植到Windows,但现在只能在OS X和Linux上运行。

  3. CRAN上有两个附加软件包 - getoptoptparse - 它们都是为命令行解析编写的。

编辑11月2015:新的替代品出现,我全心全意建议doctopt

+8

+1指向'optparse'包的指针。 – reprogrammer 2012-01-14 22:14:10

+2

并有[argparse](http://cran.r-project.org/web/packages/argparse/index.html) – gkcn 2013-08-13 13:12:51

79

将此添加到脚本的顶部:

args<-commandArgs(TRUE) 

然后你可以称之为args[1]传递的参数,args[2]

然后运行

Rscript myscript.R arg1 arg2 arg3 

如果你的ARG游戏带空格的字符串,用双引号括起来。

+7

这只适用于我使用args <-commandArgs(TRUE)(注意大写字母A) 。 – 2012-04-27 02:24:28

+0

你需要arg1之前的args吗? – philcolbourn 2017-05-24 11:34:38

+0

@philcolbourn编号 – 2018-02-19 10:40:25

4

在bash,可以构造这样的命令行:

$ z=10 
$ echo $z 
10 
$ Rscript -e "args<-commandArgs(TRUE);x=args[1]:args[2];x;mean(x);sd(x)" 1 $z 
[1] 1 2 3 4 5 6 7 8 9 10 
[1] 5.5 
[1] 3.027650 
$ 

可以看到,可变$z通过bash外壳与“10”被取代的,该值是通过commandArgs拾取并输入args[2],由R执行的范围命令x=1:10等等

3

参考文献:有一个函数args(),它检索R函数的参数,不要与名为args的参数向量混淆

+1

这几乎肯定不是这种情况。只有功能可以屏蔽功能。创建一个与函数名称相同的变量不会掩盖该函数。请参阅此问题和答案:http://stackoverflow.com/q/6135868/602276 – Andrie 2011-11-09 08:46:40

+0

没错,它并不掩盖它。一般来说,我尽量避免使用R中已经存在的名称命名函数和变量。 – Tim 2011-11-10 02:46:36

12

尝试库(getopt)...如果你想让事情变得更好。例如:

spec <- matrix(c(
     'in'  , 'i', 1, "character", "file from fastq-stats -x (required)", 
     'gc'  , 'g', 1, "character", "input gc content file (optional)", 
     'out' , 'o', 1, "character", "output filename (optional)", 
     'help' , 'h', 0, "logical", "this help" 
),ncol=5,byrow=T) 

opt = getopt(spec); 

if (!is.null(opt$help) || is.null(opt$in)) { 
    cat(paste(getopt(spec, usage=T),"\n")); 
    q(); 
} 
0

我只是放在一个很好的数据结构和处理链来产生这种开关行为,不需要库。我确信它已经实现了很多次,并且遇到了这个线程寻找的例子 - 我想我会插入。

我甚至没有特别需要标志(这里唯一的标志是调试模式,创建一个变量,我将检查它作为启动下游函数的条件if (!exists(debug.mode)) {...} else {print(variables)})。下面的标志检查lapply语句产生如下:

if ("--debug" %in% args) debug.mode <- T 
if ("-h" %in% args || "--help" %in% args) 

其中args是从命令行参数中读出的变量(一个字符向量,相当于c('--debug','--help')当提供这些上例如)

它是可重复使用的任何其他标志和你避免所有的重复,和没有图书馆所以没有依赖性:

args <- commandArgs(TRUE) 

flag.details <- list(
"debug" = list(
    def = "Print variables rather than executing function XYZ...", 
    flag = "--debug", 
    output = "debug.mode <- T"), 
"help" = list(
    def = "Display flag definitions", 
    flag = c("-h","--help"), 
    output = "cat(help.prompt)")) 

flag.conditions <- lapply(flag.details, function(x) { 
    paste0(paste0('"',x$flag,'"'), sep = " %in% args", collapse = " || ") 
}) 
flag.truth.table <- unlist(lapply(flag.conditions, function(x) { 
    if (eval(parse(text = x))) { 
    return(T) 
    } else return(F) 
})) 

help.prompts <- lapply(names(flag.truth.table), function(x){ 
# joins 2-space-separatated flags with a tab-space to the flag description 
    paste0(c(paste0(flag.details[x][[1]][['flag']], collapse=" "), 
    flag.details[x][[1]][['def']]), collapse="\t") 
}) 

help.prompt <- paste(c(unlist(help.prompts),''),collapse="\n\n") 

# The following lines handle the flags, running the corresponding 'output' entry in flag.details for any supplied 
flag.output <- unlist(lapply(names(flag.truth.table), function(x){ 
    if (flag.truth.table[x]) return(flag.details[x][[1]][['output']]) 
})) 
eval(parse(text = flag.output)) 

注意,在这里flag.details命令被存储为字符串,然后用eval(parse(text = '...'))评估。对于任何严肃的脚本,Optparse显然都是可取的,但最小功能代码有时候也是很好的。

输出示例:

$ Rscript check_mail.Rscript --help 
--debug Print variables rather than executing function XYZ... 

-h --help Display flag definitions
6

由于optparse已经在答复中提到了几次,并提供了命令行处理的综合套件,这里是你如何使用它很短的简单的例子,假设输入文件存在:

script.R:

library(optparse) 

option_list <- list(
    make_option(c("-n", "--count_lines"), action="store_true", default=FALSE, 
    help="Count the line numbers [default]"), 
    make_option(c("-f", "--factor"), type="integer", default=3, 
    help="Multiply output by this number [default %default]") 
) 

parser <- OptionParser(usage="%prog [options] file", option_list=option_list) 

args <- parse_args(parser, positional_arguments = 1) 
opt <- args$options 
file <- args$args 

if(opt$count_lines) { 
    print(paste(length(readLines(file)) * opt$factor)) 
} 

鉴于任意文件blah.txt有23行。

在命令行上:

Rscript script.R -h输出

Usage: script.R [options] file 


Options: 
     -n, --count_lines 
       Count the line numbers [default] 

     -f FACTOR, --factor=FACTOR 
       Multiply output by this number [default 3] 

     -h, --help 
       Show this help message and exit 

Rscript script.R -n blah.txt输出[1] "69"

Rscript script.R -n -f 5 blah.txt输出[1] "115"