getopt


getopt関数は「そういうのがある」というぐらいの認識で、実は今まで使ったことがなかったんだけど、今自分が構想を練っているアプリケーションで、 コマンドラインオプションの解析が必要になりそうなので、使ってみた。例えば、以下のような形式のコマンドを解釈したいとする。

cmd command [option] args


解析したいのは[option]以降なので、getoptにはmainのargvをそのまま渡すのではなく、1個ずらしたものを渡す。以下、C++のコード。ほとんどCだけど。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>

void usage();
int dispatchCommand(char *command);
void dispatchOptions(int argc, char *argv[]);

int dispatchCommand (char *command) {
  int len;
  int commandType = 0;
  len = strlen(command);
  if (strncmp(command, "command1", len) == 0) {
    commandType = 1;
  } else if (strncmp(command, "command2", len) == 0) {
    commandType = 2;
  } else {
    printf("command is invalid.\n");
  }
  return commandType;
}

void dispatchOptions (int argc, char *argv[]) {
  int ch;
  extern char* optarg;
  extern int optind, opterr;
  while ((ch = getopt(argc, argv, "rn:")) != -1){
    switch (ch){
    case 'r':
      printf("Option r is selected.\n");
      break;
    case 'n':
      printf("Option n is selected.\n");
      printf("Value = %d\n",atoi(optarg));
      break;
    default:
      usage();
    }
  }
  argc -= optind;
  argv += optind;

  printf("arg1 = %s\n", argv[0]);
  printf("arg2 = %s\n", argv[1]);
}

void usage(void){
  fprintf(stderr, "Usage: cmd command [option] args\n");
  fprintf(stderr, " -r    : option r\n");
  fprintf(stderr, " -n #  : option b (# is a number)\n");
  exit(1);
}

int main(int argc,char *argv[]){
  
  if (argc < 2) {
    printf("few argument\n");
    return 0;
  }
  
  printf("commandNumber:%d\n", dispatchCommand(argv[1]));

  if (argc < 3) {
    printf("few argument\n");
    return 0;
  }
  char **optargs; 
  optargs = ++argv;
  dispatchOptions(--argc, optargs);
  
  return 0;
}


う〜ん、オプションで使えるのは一文字なのか。
getopt_longって関数だと--filesみたいなことができるみたいだけど、
それはまた今度。いくつかのオープンソースソフトウェアのソースコードを見てみたけど、
生のgetopt使ってるのは案外少ないなあ。中にはif-elseだけで全部処理してるのもあったし。

実行結果

narazuya@bokko% g++ -o getopt_test test.cpp 
narazuya@bokko% ./getopt_test command1 -r 10 20
commandNumber:1
Option r is selected.
arg1 = 10
arg2 = 20
narazuya@bokko% ./getopt_test command1 -n 10 20
commandNumber:1
Option n is selected.
Value = 10
arg1 = 20
arg2 = (null)
narazuya@bokko% ./getopt_test command2 -r 10 20
commandNumber:2
Option r is selected.
arg1 = 10
arg2 = 20
narazuya@bokko% ./getopt_test command2 -n 10 20
commandNumber:2
Option n is selected.
Value = 10
arg1 = 20
arg2 = (null)
narazuya@bokko%