Reputation: 68396
I am writing a R script which I will be running as a script from the command line. I am passing command line arguments to the script using keywords as follows:
myscript.R --arg1=100 --arg2='hello' --arg3=3.14159
I want to write an R function that will return the command line values into a dictionary like object (i.e. a list of lists in R), filling unsupplied arguments with defaults.
for e.g.
parseArguments <- function() {
options <- commandArgs(TRUE)
# options now contains "--arg1=100 --arg2='hello' --arg3=3.14159"
# parse string held in variable named options and stuff into a list
# .... Do some string manip ....
args <- list()
args['arg1'] <- 100
args['arg2'] <- 'hello'
args['arg3'] <- 3.14159
args['arg4'] <- 123 # Not found in parsed line so we use a hard coded default
return (args)
}
Can someone help fill in the blanks?
Upvotes: 3
Views: 10156
Reputation: 32351
You can split each argument into
the name and value parts, using strsplit
or a regular expression.
The following does not try to check the type of the arguments:
everything will be returned as a string.
parseArgs <- function(...) {
o <- commandArgs(TRUE)
# The defaults arguments should be named
defaults <- list(...)
stopifnot( length(defaults) == length(names(defaults)) )
stopifnot( all( names(defaults) != "" ) )
# All the arguments should be of the form "--foo=bar"
re <- "^--(.*?)=(.*)"
stopifnot( all(grepl(re, o)) )
# Extract the values and names
r <- gsub(re, "\\2", o)
names(r) <- gsub("^--(.*?)=(.*)", "\\1", o)
r <- as.list(r)
# Add the default values
missing <- setdiff( names(defaults), names(r) )
append(r, defaults[missing])
}
print( parseArgs() )
print( parseArgs(foo=1, bar=2) ) # With default values
Upvotes: 3
Reputation: 263332
> parseArguments <- function() {
+ text1 = "--arg1=100 --arg2='hello' --arg3=3.14159"
+ eval(parse( text= gsub("\\s", ";", gsub("--","", text1))))
+ args <- list()
+ args['arg1'] <- arg1
+ args['arg2'] <- arg2
+ args['arg3'] <- arg3
+ args['arg4'] <- 123 # Not found in parsed line so we use a hard coded default
+
+ return (args)
+ }
> argres <- parseArguments()
> argres
$arg1
[1] 100
$arg2
[1] "hello"
$arg3
[1] 3.14159
$arg4
[1] 123
To address the unkown number of arguments modification to the problem:
parseArguments <- function() {
text1 = "--arg1=100 --arg2='hello' --arg3=3.14159"
eval(parse(text=gsub("\\s", ";", gsub("--","", text1))))
args <- list()
for( ar in ls()[! ls() %in% c("text1", "args")] ) {args[ar] <- get(ar)}
return (args)
}
argres <- parseArguments()
argres
#---------
$arg1
[1] 100
$arg2
[1] "hello"
$arg3
[1] 3.14159
Upvotes: 3