1

I have an R script I intend to call from the command line, which includes a function which may take option ... arguments. I'd like to parse any arguments given at the command line as arguments in .... How might I do this?

I've tried the rlang package. I thought something like this would work:

z <- c('x=1', 'y=2') #but actually, z <- commandArgs(T)
c(UQS(z))

Here I would expect to get a vector as if I had called c(x=1, y=2). Instead I get a list of names x=1 &c.

Empiromancer
  • 3,778
  • 1
  • 22
  • 53

2 Answers2

4

I agree with the previous answer that this is a bit unsafe. That said, one hacky way to achieve this somewhat safely is to take advantage of environments.

First, create a blank environment:

args_env <- env()

Parse-eval your arguments inside that environment.

z <- c("x=1", "y=2")
eval(parse(text = z), envir = args_env)

Convert the environment to a list:

args_list <- as.list(args_env)

And now, you should be able to use do.call to pass arguments in.

do.call(f, args_list)
Alexey Shiklomanov
  • 1,592
  • 13
  • 23
  • I agree that this would be an unsafe thing to do in general. I'm happy to accept your solution (and your warning) since I'm doing this in a *very* limited circumstance – Empiromancer Mar 09 '18 at 18:57
0

I wouldn't necessary recommend your approach. It would be safer to use a package like optparse to properly parse your command line parameters.

But that said, if you want to treat arbitrary strings as R code, you can just eval(parse(test=)) it. Of if you really want to use rlang, you can use eval_tidy/parse_expr.

args <- c('x=1', 'y=2')
z <- eval_tidy(parse_expr(paste0("c(", paste(args, collapse=","), ")")))
# or
z <- eval(parse(text=paste0("c(", paste(args, collapse=","), ")")))

You need this because things in the form a=b can't exist independently outside of an expression otherwise it's interpreted as assignment. If you needed to play with just the name on the left or the value on the right, there might be smarter ways to do this, but if you pass it as one character chunk, you'll need to parse it.

MrFlick
  • 195,160
  • 17
  • 277
  • 295