Homunculus Reticulli
Homunculus Reticulli

Reputation: 68396

Parsing a string in R

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

Answers (2)

Vincent Zoonekynd
Vincent Zoonekynd

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

IRTFM
IRTFM

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

Related Questions