R语言接受命令行参数的三种方式
最近要用一下R的命令行,但是发现命令行参数不是很友好,就总结了一下目前常用的R的命令行参数的接受方法。
平常我们使用R语言的时候常常都是在交互界面中一步一步更改运行,所以一般用不到命令来执行,但有时候对于批量运行或者某种情况下数据较大,直接在Rstudio中运行卡顿,在把代码提前调试好后后续使用命令行可能更好,另外一半我们编写好的脚本搭建pipeline的时候需要命令行执行,这个时候就必须要命令行来实现了。
R接受命令的参数有三个常见的方法
commandArgs()
、
getopt()
、
OptionParser()
,其中第一个是R自带的函数,后面两个分别来自包
getopt
和
optparse
。
运行命令行脚本
在之前了解一下R语言的命令行方式,下面在windows的cmd中还是Mac或者Linux的终端中的命令行用法都是这样的。
[options]
是R脚本解释器的参数,
[args]
是脚本的参数。如果是
Linux
或者
Mac
的话可以省略
Rscipt
,在脚本第一行加上
shebang
行
#!/usr/bin/Rscript
。
Rscript [options] file [args]
下面是一个R脚本示例test.R
print("Hello R!")
在终端中运行
Rscript test.R
[1] "Hello R!"
1. commandArgs()
这是个R
的内置命令,和perl
的@ARGV
或者和python
的sys.argv
类似,就是将来自于命令的参数存入向量(数组)中。但是与perl
和python
的不同,它的前面几个元素不是命令行的参数,先尝试打印一下这个参数是怎样的。
下面是一个测试脚本test.R
# commandArgs()就返回一个包含参数信息的向量
args <- commandArgs()
print(args)
Rscript test_args.R Hello R
[1] "C:\\PROGRA~1\\R\\R-35~1.2\\bin\\x64\\Rterm.exe"
[2] "--slave"
[3] "--no-restore"
[4] "--file=test_args.R"
[5] "--args"
[6] "Hello"
[7] "R"
参数解释:
那么就是说输入的参数是从第6个开始(注意!R的索引与python或者perl不同,它是从1开始的。)
其实对于参数的位置是可变的,在R所在路径和R脚本的路径这两个参数之间是Rscript的参数,这些参数的数量是可变的(其实这里也就是是按照顺序的Rscript
的参数,后面的脚本其实也就是一个参数而已,这里看来和python或者perl是差不多的。)
2和3这两个参数虽然我们没有输入,但是是作为Rscript的默认参数的。
参数索引 1 2 3 4 5 6 7
Rscript --slave --no-restore --file=test_args.R --args Hello R
这样一来就会导致R脚本的参数的索引不固定,针对这种情况,你也可以添加一个参数来削掉R脚本参数之前的参数了。
args <- commandArgs(trailingOnly = TRUE)
print(args)
[1] "Hello"
[2] "R"
这样R脚本的参数就从1
开始了。
但是这样对于参数解析的顺序是需要的,也就是说脚本接受的参数的输入需要严格按照顺序来,有时候为了区分参数使用这个命令其实是不方便的。使用特定的flag来区分参数是需要,当然R也是有相应的包来做这些事情的。
2. getopt
在使用之前需要安装对应的包:
install.packages("getopt")
这个包的getopt()
函数使用方法是
getopt(spec = NULL, opt = commandArgs(TRUE),command = get_Rscript_filename(), usage = FALSE,debug = FALSE)
spec
:这个参数需要一个矩阵,这个矩阵描述了接受参数的flag以及参数的形式等等信息
参数的短名称(一个字符)
这个flag对应的参数形式(0表示flag不接受参数;1表示可接可不接;2表示必须接参数)
参数的类型(logical;integer;double;complex;character;numeric)
"first_arg"
"double"
"This arg is the first arguments"
spec <- matrix(
c("first", "f", 2, "integer", "This is first!",
"second", "s", 1, "character", "This is second!",
"third", "t", 2, "double", "This is third!",
"help", "h", 0, "logical", "This is Help!"),
byrow=TRUE, ncol=5)
# 使用getopt方法
opt <- getopt(spec=spec)
# opt实际上就是一个列表,直接使用$来索引到对应的参数的值
print(opt$first)
print(opt$second)
print(opt$third)
在命令行执行
Rscript test.R -f 123 -t 1.1 -s Hello
[1] 123
[1] "Hello"
[1] 1.1
但是这里如果参数输出不正确的时候并不能弹出详细的帮助信息,下面增加一些信息就可以得到相应的帮助信息了
library(getopt)
# 首先将第一个参数的具体信息进行描述
spec <- matrix(
# 每行五个,第五个可选,也就是说第五列可以不写
# byrow 按行填充矩阵的元素
# ncol 每行填充五个元素
c("first", "f", 2, "integer", "This is first!",
"second", "s", 1, "character", "This is second!",
"third", "t", 2, "double", "This is third!",
"help", "h", 0, "logical", "This is Help!"),
byrow=TRUE, ncol=5)
# 使用getopt方法,注意这里的usage默认是关闭的,这里不能打开
opt <- getopt(spec=spec)
# 这个时候需要将usage参数打开,这样getpot()就会返回一个特定写法的帮助文件
# 当然你也可以自己写帮助,然后将if判断语句中的打印的信息换成你自己定义的帮助信息
if( !is.null(opt$help) || is.null(opt$first) || is.null(opt$third) ){
# ... 这里你也可以自定义一些东放在里面
cat(paste(getopt(spec=spec, usage = T), "\n"))
quit()
# opt实际上就是一个列表,直接使用$来索引到对应的参数的值
print(opt$first)
print(opt$second)
print(opt$third)
命令行执行
Rscript test.R -h
Usage: test_args.R [-[-first|f] [<integer>]] [-[-second|s] <character>] [-[-third|t] [<double>]] [-[-help|h]]
-f|--first This is first!
-s|--second This is second!
-t|--third This is third!
-h|--help This is Help!
解析参数的包不止一个,R也不例外,这里也有另外一个包也是干同样的事情的,但是它的用法与上面的getopt
包有一定差别。
3. optparse
使用之前安装包
install.packages("optparse")
其中的方法OptionParser()
的用法为:
OptionParser(usage = "usage: %prog [options]", option_list = list(),
add_help_option = TRUE, prog = NULL, description = "",
epilogue = "")
其中最重要的参数是option_list
,这个参数接受一个列表,这个列表是被用来描述命令参数的解析方式的。
下面是一个例子,将下列代码存到test.R
文件中:
library(optparse)
# 描述参数的解析方式
option_list <- list(
make_option(c("-f", "--first"), type = "integer", default = FALSE,
action = "store", help = "This is first!"
make_option(c("-s", "--second"), type = "character", default = FALSE,
action = "store", help = "This is second!"
make_option(c("-t", "--third"), type = "double", default = FALSE,
action = "store", help = "This is third!"
# make_option(c("-h", "--help"), type = "logical", default = FALSE,
# action = "store_TRUE", help = "This is Help!"
# 解析参数
opt = parse_args(OptionParser(option_list = option_list, usage = "This Script is a test for arguments!"))
print(opt)
注意,这个模块不用加上-h
的flag,不然会报错:
Error in parse_args(OptionParser(option_list = option_list)) :
Error in getopt(spec = spec, opt = args) :
redundant long names for flags (column 1 of spec matrix).
其实从这个报错信息可以看出来这个模块其实还是调用了getopt
模块
Rscript test.R -f 10 -s Hello -t 1.1
$first
[1] 10
$second
[1] "Hello"
$third
[1] 1.1
$help
[1] FALSE
如果加上-h
Usage: This Script is a test for arguments!
Options:
-f FIRST, --first=FIRST
This is first!
-s SECOND, --second=SECOND
This is second!
-t THIRD, --third=THIRD
This is third!
-h, --help
Show this help message and exit
这里Usage
后面跟的信息时候在OptionParser中usage
方法指定。
试了试这三个方式,第一个是最简洁的,如果你的脚本输出入参数很少(只有一两个的话),那就采用commandArgs()
方法吧,使用轻便;其他两个模块干的活很相似,但是我感觉第三个optparse
在接受参数的描述上与python的optparse
模块的风格更加像一些,好像模块名也是一样的,里面的参数都很像,所以用过python的会对这个模块很熟悉,另外就是自动生成的帮助文档相对于getopt
的来说更加友好一些,生成的解析命令行的描述不容易出错。但是就风格上,getopt
更加轻便,解析命令行的参数的描述就是一个矩阵,看起来更加清晰一些。
如需转载,请注明来源:https://www.jianshu.com/p/8797972113d7