Rにも
ライブラリ
で getopt(1) があるようですが, 元のgetoptと違い,
% foo.R --flag=xxx file1 file2 の file1 file2 のように,
オプションの引数でない引数を許さない(!)ようなので,
簡単なラッパーを書いてみました。
使い方は中の main () にある通りですが, 元のように byrow=T のように余計なこと
を書く必要がなく,
opts <- getopts ( c(
"alpha", "a", 1, "double",
"iters", "N", 2, "integer",
"output", "o", 2, "character",
"help", "h", 0, "logical"
), usage, 2)
のように書くだけで使えます。&, opts にある名残り opt$ARGS (上の一般引数に
対応しようとした名残りだと思われます) を消し, 指定されなかったオプションには
NAを代入するので, opt$foo のようにそのまま他に引数として渡すことができます。
最後の2は一般引数の数で, さすがにオプションと混じった場合には使えませんが,
一般引数は最初に置いても最後に置いてもよいようにしておきました。
#!/usr/local/bin/Rscript
#
# opts.R
# for easy use of getopt(1).
# $Id: opts.R,v 1.5 2020/10/07 00:21:00 daichi Exp $
#
library("getopt")
getopts <- function (spec, usage, n, ...)
{
res <- list()
tokens <- commandArgs (T)
if (length(tokens) < n) {
usage ()
}
if (substr(tokens[1], 1, 1) == "-") {
res$args <- tail (tokens, n)
res$opts <- getopt (matrix (spec, byrow=T, ncol=4),
head (tokens, -n), ...)
} else {
res$args <- head (tokens, n)
res$opts <- getopt (matrix (spec, byrow=T, ncol=4),
tail (tokens, -n), ...)
}
# fill unused options by NA
names <- spec [seq(1,length(spec),by=4)]
for (name in names) {
if (is.null(res$opts[[name]])) {
res$opts[[name]] <- NA
}
res$opts$ARGS <- NULL
}
res
}
main <- function ()
{
usage <- function ()
{
cat ('usage: % opts.R --iter=iters --output=file train model\n')
quit ()
}
opts <- getopts ( c(
"alpha", "a", 1, "double",
"iters", "N", 2, "integer",
"output", "o", 2, "character",
"help", "h", 0, "logical"
), usage, 2)
if (!is.na(opts$opts$help)) {
usage ()
}
print (opts$args)
print (opts$opts)
}
if (!interactive() & sys.nframe() == 0) {
main ()
}