简体   繁体   中英

Seperating options from non-option arguments in a command-line program

I am trying to write a limited version of ls w/ some options.

However, I am stuck on the problem of parsing out my options from my arguments in a clean manner.

For example:

$ ls -l -t somefile anotherFile

$ ls somefile -lt anotherFile

have the same behavior.

This poses two problems for me:

  1. It makes using argc a bit more difficult. For example I would consider the arguments ls -lt and ls to both have 0 arguments (other than the name of the command) however argc counts -l as an argument.

Therefore the naive implementation of :

if( argc == 1) {list all the contents of cwd}

does not work.

Is there a built-in way to get the options as well as the option count, or do I have to roll my own function?

  1. I have to consider all the different ways options can be arranged and be careful not to get an option mixed up as a file name or directory name. It seems like the cleanest solution is to separate the options from the file arguments from the start. Is there an idiomatic way to do this / is there standard library calls that do this?

There is no built-in argument parsing help, but getopt is the "standard" method for argument parsing.

For simple apps, I sometimes roll my own with something like:

int pos=0;
argc--;argv++;
while (argc > 0) {
  if (*argv[0]=='-') {
     switch ((*argv)[1]) {
       case 'l': //-l argument
         save_option_l(++argv);
         argc--; //we consumed one name
         break;
       //... other -options here ...
       default:
         usage("unrecognized option %s", *argv);   
     }
   }
   else {
     save_positional_argument(argv,pos++);
   }
   argv++;
   argc--;
}

In this case, I require the modifiers to directly follow the flags. Don't support variable usage like your first example, unless there are very strong reasons to do so.

If you have Gnu's implementation of getopt , it will do all that for you.

Posix standard getopt terminates option processing when it hits the first non-option argument. That conforms to Posix guidelines for utility argument parsing, and many of us prefer this behaviour. But others like the ability to intermingle options and non-options, and that's the norm for Gnu utilities unless you set an environment variable with the ungainly name POSIXLY_CORRECT .

Consistent with that preference, Gnu getopt parses arguments:

The default is to permute the contents of argv while scanning it so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this.

Note the wording about permuting arguments. This means that if you start with

ls somefile -lt anotherFile

Gnu getopt will:

  1. Report a l
  2. Report a t
  3. Report end of options (-1), leaving optind with the value 2 and argv now looking like:

     ls -lt somefile anotherFile 

So now you can process your non-option arguments with:

for (int argno = optind; argno < argc; ++argno) {
  /* Do something with argv[argno] */
}

Also, you can tell how many non-option arguments you received with argc-optind , and if argc == optind , you know there weren't any.

Unbundling -lt into two options is standard Posix getopt behaviour . You can combine options lime that as long as the first one doesn't take an argument.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM