6

Is there an alternative way to pass two arguments to an option as a single string when using getopt()? Normally I would do the following:

./command -o "key value" [command arguments]

Then I would have to split the argument string explicitly:

 while ((op = getopt(argc, argv, "o:")) != EOF) {
    switch (op) {
             case 'o': 
                 char* result = NULL;
                 result = strtok_r(optarg," ");
                 while(result) {
                     /* DO STUFF */
                     result = strtok(NULL," ");
                 }

                 break;
             default:
                 printUsage()
                 break;
   }

So, I am wondering if it is possible to use the following and make getopt() treat "value" as -o second argument rather than the command argument?

./command -o key value [command arguments]
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
ziu
  • 2,634
  • 2
  • 24
  • 39

2 Answers2

12

The POSIX standard getopt() does not support multiple arguments for a single flag letter. There are a couple of options available to you.

One option is to specify the names as arguments to separate option letters (or use the same one twice):

./command -o key -v value
./command -o key -o value

Another option is to use the POSIX standard getsubopt() and a command line notation such as:

./command -o key=value

This works pretty well for your shown scenario if the set of keys is relatively small (not so well if they are large, but you could do without getsubopt() then and simply parse optarg for the = yourself.

Another option is to write a command line parser that will accept multiple arguments as you require. I wrote one to be able to parse the diverse and ill-disciplined argument handling on programs that we use at work - and it is not dreadfully difficult (though it wasn't altogether easy, either). It specifically has to handle N (N > 1) option values after a single flag. Contact me (see my profile) if you want to look at the source. There are some tricky issues to resolve, such as what happens if you expect 3 names after the option letter, but one of the first three arguments starts with a dash -, or -- appears. I only allow a fixed number of arguments, not a variable number, but that is in part because my use cases didn't need to cover a variable number (and it doesn't sound as if yours would, either).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

How would getopt know where your -o options end, and where your command arguments start?

One simple workaround is to use to -o specifiers:

$ cat t.c
#include<stdio.h>
#include<getopt.h>

int main(int argc, char **argv)
{
    char op;
    while ((op = getopt(argc, argv, "o:")) != EOF) {
        switch (op) {
            case 'o':
                printf("Option: %s\n", optarg);
                break;
            default:
                break;
        }
    }
}
$ gcc t.c
$ ./a.out -o one -o two -o three
Option: one
Option: two
Option: three
Mat
  • 202,337
  • 40
  • 393
  • 406
  • I know this workaround, but since the two option arguments are bound together (key value pair), I cannot split them up – ziu Dec 19 '11 at 10:57
  • The use two switches `-ok key -ov val` and add a bit of logic to make sure they are specified in the right order. Or see other options in the previous question I linked. – Mat Dec 19 '11 at 10:59