Передача нескольких аргументов через командную строку в R

Я пытаюсь передать несколько аргументов пути к файлу через командную строку в Rscript, который затем можно обработать с помощью парсера аргументов. В конце концов, я бы хотел что-то вроде этого

Rscript test.R --inputfiles fileA.txt fileB.txt fileC.txt --printvar yes --size 10 --anotheroption helloworld -- etc...

передаются через командную строку и при синтаксическом анализе имеют результат в виде массива в R

args$inputfiles =  "fileA.txt", "fileB.txt", "fileC.txt"

Я пробовал несколько парсеров, включая optparse и getopt, но ни один из них, похоже, не поддерживает эту функцию. Я знаю, что argparse есть, но в настоящее время он недоступен для версии R 2.15.2.

Любые идеи?

Спасибо


person Omar Wagih    schedule 09.12.2012    source источник
comment
Не могли бы вы рассказать, почему решение @agstudy не работает? Это довольно точно   -  person Ricardo Saporta    schedule 09.12.2012
comment
Также возможен дубликат stackoverflow.com/questions/2151212/   -  person Ricardo Saporta    schedule 09.12.2012
comment
@RicardoSaporta не дублируется. Это немного другое.   -  person agstudy    schedule 10.12.2012


Ответы (5)


Хотя он не был выпущен на CRAN, когда был задан этот вопрос, сейчас существует бета-версия модуля argparse, которая может это сделать. По сути, это оболочка вокруг популярного одноименного модуля python, поэтому для его использования необходимо установить последнюю версию python. См. Примечания по установке для получения дополнительной информации. Базовый пример включал суммирование произвольно длинного списка чисел, который не должно быть сложно изменить, чтобы вы могли получить произвольно длинный список входных файлов.

> install.packages("argparse")
> library("argparse")
> example("ArgumentParser")
person Trevor    schedule 01.03.2013

То, как вы описываете параметры командной строки, отличается от того, как большинство людей ожидает их использования. Обычно опция командной строки принимает единственный параметр, а параметры без предшествующей опции передаются как аргументы. Если аргумент может принимать несколько элементов (например, список файлов), я бы предложил проанализировать строку с помощью strsplit ().

Вот пример использования optparse:

library (optparse)
option_list <- list ( make_option (c("-f","--filelist"),default="blah.txt", 
                                   help="comma separated list of files (default %default)")
                     )

parser <-OptionParser(option_list=option_list)
arguments <- parse_args (parser, positional_arguments=TRUE)
opt <- arguments$options
args <- arguments$args

myfilelist <- strsplit(opt$filelist, ",")

print (myfilelist)
print (args)

Вот несколько примеров выполнения:

$ Rscript blah.r -h
Usage: blah.r [options]


Options:
    -f FILELIST, --filelist=FILELIST
        comma separated list of files (default blah.txt)

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


$ Rscript blah.r -f hello.txt
[[1]]
[1] "hello.txt"

character(0)
$ Rscript blah.r -f hello.txt world.txt
[[1]]
[1] "hello.txt"

[1] "world.txt"
$ Rscript blah.r -f hello.txt,world.txt another_argument and_another
[[1]]
[1] "hello.txt" "world.txt"

[1] "another_argument" "and_another"
$ Rscript blah.r an_argument -f hello.txt,world.txt,blah another_argument and_another
[[1]]
[1] "hello.txt" "world.txt" "blah"     

[1] "an_argument"      "another_argument" "and_another"     

Обратите внимание, что для strsplit вы можете использовать регулярное выражение для определения разделителя. Я бы предложил что-то вроде следующего, что позволит вам использовать запятые или двоеточия для разделения вашего списка:

myfilelist <- strsplit (opt$filelist,"[,:]")
person Aphoid    schedule 22.08.2016

Перед вашим скриптом test.R вы помещаете это:

args <- commandArgs(trailingOnly = TRUE)

hh <- paste(unlist(args),collapse=' ')
listoptions <- unlist(strsplit(hh,'--'))[-1]
options.args <- sapply(listoptions,function(x){
         unlist(strsplit(x, ' '))[-1]
        })
options.names <- sapply(listoptions,function(x){
  option <-  unlist(strsplit(x, ' '))[1]
})
names(options.args) <- unlist(options.names)
print(options.args)

получить :

$inputfiles
[1] "fileA.txt" "fileB.txt" "fileC.txt"

$printvar
[1] "yes"

$size
[1] "10"

$anotheroption
[1] "helloworld"
person agstudy    schedule 09.12.2012
comment
У меня это не работает. Мои аргументы намного сложнее. Проходит примерно 8-10 вариантов. Следовательно, парсеры arg - person Omar Wagih; 09.12.2012
comment
@ Омар сложный? как? можешь привести пример? - person agstudy; 09.12.2012
comment
Конечно, я добавил пример в свой вопрос. Ваше решение сработало бы для меня, только если бы файлы были единственным, что я передавал в качестве аргумента. Нет? - person Omar Wagih; 10.12.2012
comment
@Omar Если вас устраивает сценарий vbs, вы можете выполнить его и вызвать его из R. Я думаю, это легко найти в SO. - person agstudy; 10.12.2012
comment
Я продолжаю находить недостающие функции с помощью этого быстрого метода. Например: файлы с пробелами в них при экранировании становятся файлом \ a.txt. Этого не обнаружено. Может ли кто-нибудь предложить другой более надежный способ анализа этих аргументов? или мне придется писать парсер снизу вверх? - person Omar Wagih; 11.12.2012
comment
@Omar хорошая идея сделать это снизу и поделиться конечно. - person agstudy; 11.12.2012

После поиска и избегания написания нового пакета снизу вверх я решил, что лучший способ ввести несколько аргументов с помощью пакета optparse - разделить входные файлы символом, который, скорее всего, незаконно включать в имя файла ( например, двоеточие)

Rscript test.R --inputfiles fileA.txt:fileB.txt:fileC.txt etc...

В именах файлов также могут быть пробелы, если они экранированы (optparse позаботится об этом)

Rscript test.R --inputfiles file\ A.txt:file\ B.txt:fileC.txt etc...

Ultimatley, было бы неплохо иметь пакет (возможно, модифицированную версию optparse), который бы поддерживал несколько аргументов, как указано в вопросе и ниже

Rscript test.R --inputfiles fileA.txt fileB.txt fileC.txt

Можно было бы подумать, что такие тривиальные функции будут реализованы в широко используемом пакете, таком как optparse

Ваше здоровье

person Omar Wagih    schedule 10.12.2012
comment
почему бы не объяснить, как вы используете пакет optparse? - person agstudy; 11.12.2012
comment
Это выходит за рамки моего вопроса. Примеры optparse можно найти в документации здесь cran.r-project.org /web/packages/optparse/optparse.pdf - person Omar Wagih; 11.12.2012

Решение @agstudy не работает должным образом, если входными аргументами являются списки одинаковой длины. По умолчанию sapply сворачивает входные данные одинаковой длины в матрицу, а не в список. Исправление достаточно простое, просто явно установите для упрощения значение false в sapply, анализирующем аргументы.

args <- commandArgs(trailingOnly = TRUE)

hh <- paste(unlist(args),collapse=' ')
listoptions <- unlist(strsplit(hh,'--'))[-1]
options.args <- sapply(listoptions,function(x){
         unlist(strsplit(x, ' '))[-1]
        }, simplify=FALSE)
options.names <- sapply(listoptions,function(x){
  option <-  unlist(strsplit(x, ' '))[1]
})
names(options.args) <- unlist(options.names)
print(options.args)
person user2687794    schedule 11.12.2014