GETOPT(3)

名前
getopt - コマンドラインオプションを解釈する

書式
#include <unistd.h>

int getopt(int argc, char * const argv[],
           const char *optstring);

extern char *optarg;
extern int optind, opterr, optopt;

#include <getopt.h>

int getopt_long(int argc, char * const argv[],
           const char *optstring,
           const struct option *longopts, int *longindex);

int getopt_long_only(int argc, char * const argv[],
           const char *optstring,
           const struct option *longopts, int *longindex);

説明
getopt() 関数はコマンドライン引き数を解釈する。 getopt() がとる引き数 argc と argv は、それぞれプログラムの起動時に main() 関数に渡された引き数の個数と配列である。 argv の要素のうち `-' で始まるもの (かつ `-' 単独や `--' で はないもの) はオプション要素 (option element) とみなされる。この要素 から先頭の `-' を除いた文字はオプション文字 (option character) とされる。 getopt() は、繰り返し呼び出されるごとに、次のオプション文字を返す。

新たなオプション文字を見つけると、 getopt() はその文字を返し、 外部変数 optind とスタティックな変数 nextchar を更新する。 これらによって、 getopt() は次回の呼び出しの際に、以降のオプショ ン文字や argv 要素のスキャンを継続できる。

オプション文字がそれ以上見つからなくなると、 getopt() は EOF を返す。そして optind は、 argv の要素のうち、 オプションでない最初の要素を示すようになる。

optstring は受け付けるオプション文字からなる文字列である。文字のあとにコ ロン (:) が置かれている場合は、オプションには引き数が必要であることを 示す。このとき getopt は、現在注目している argv 要素で、オプション文字に引き続くテキストへのポインタか、 あるいは次の argv 要素のテキストへのポインタを optarg に代入する。 2 個連続してコロンが置かれている場合は、そのオプションは引き数をとっても とらなくてもよい。現在の argv 要素にテキストがあれば、それが optarg に返される。なければ optarg は 0 にされる。 これは GNU による拡張である。 optstring に W とそれに続くセミコロンが入っていると、 -W foo は長いオプション --foo と同じように扱われる。 (POSIX.2 は -W オプションを実装依存の拡張として予約している。) この動作は GNU による拡張であり、 GNU libc 2 以前のライブラリでは 利用できない。

デフォルトでは getopt() は argv をスキャンする際に順序を変 更し、オプション以外の要素を最後に移動する。他にも二つのモードが実装さ れている。 optstring の先頭文字が `+' であるか、環境変数 POSIXLY_CORRECT が設定されている場合には、オプションを対象とする動作は、 非オプションの引き数が現れた段階で終了する。 optstring の最初の 先頭文字が `-' である場合には、オプションでない argv 要素は、 文字コード 1 のオプションであるかのように扱われる (これを用いるプログラムは、 オプションや argv 要素を任意の順序で受け入れ、かつそれらの順序が 意味を持つように書かれている必要がある)。 `--' は特殊な引き数で、ス キャンのモードによらず、オプションのスキャンを強制的に終了させる。

オプション文字を認識しなかった場合には、 getopt() はエラーメッセー ジを標準出力に表示し、その文字を optopt に保存して `?' を返す。 呼び出したプログラムで opterr を 0 にしておけば、エラーメッセー ジの表示を抑制できる。

getopt_long() 関数は、長いオプション (二つのダッシュ `--' で始まるオプション) を受 け入れることを除いて getopt() と同じように動作する。長いオプションの名前は、他と重ならない範囲におい て短縮できる。あるいは定義されたオプションに正確にマッチするものでも (当然) かまわない。 長いオプションは引き数を取ることができ、 --arg=param または --arg param と言う形式で指定する。

longopts は struct option の要素からなる配列の、先頭要素へのポインタである。 struct option は <getopt.h> で以下のように定義されている。

struct option {
const char *name;
int has_arg;
int *flag;
int val;
};

それぞれのフィールドの意味は以下の通り。

name
    長いオプションの名前。

has_arg
    no_argument (または 0) なら、オプションは引き数をとらない。 required_argument (または 1) なら、オプションは引き数を必要とする。 optional_argument (または 2) なら、オプションは引き数をとっても とらなくても良い。

flag
    長いオプションンに対する結果の返し方を指定する。 flag が NULL なら getopt_long() は val を返す (例えば呼び 出し元のプログラムは、 val に等価なオプション文字を代入すること ができる)。 NULL 以外の場合には、 getopt_long() は 0 を返 す。このときオプションが見つかると flag がポイントする変数に val が代入される。見つからないとこの変数は変更されない。

val 返り値、または flag がポイントする変数へロードされる値。

配列の最後の要素は、全て 0 で埋められていなければならない。

longindex は、 NULL でなければ、 長いオプションのインデックスを longopts からの相対位置として保持している変数へのポインタとなる。

getopt_long_only() は getopt_long() と同様の動作をするが、 `-' も `--' と同様に、長いオプションとして扱われる。 `-' で始まる (`--' 以外の) オプションが、長いものにはマッチしないが短いものにマッ チする場合においては、それは短いオプションとして解釈される。

返り値
getopt() 関数はオプションが見つかればそのオプション文字を返す。必要な引き数が足 りないオプションがあると `:' を返す。定義されていないオプション文字が あると `?' を返す。オプションリストの最後に来た場合には EOF を返 す。

getopt_long() と getopt_long_only() も、短いオプション文字 を認識した場合にはその文字を返す。長いオプションに対しては、 flag が NULL なら val を返し、 flag が NULL 以外なら 0 を返す。エラーと EOF の返り値は getopt() と同じである。さらに `?' は、マッチが確定できない場合や余分なパラメー ターがある場合にも返る。

環境変数

POSIXLY_CORRECT
    これが設定されていると、非オプションの引き数に到達した時点でオプション に対する操作が停止される。

_<PID>_GNU_nonoption_argv_flags_
    この変数は bash 2.0 が GNU libc と通信するために用いられた。どの引き数がワイルドカード を展開した結果で、したがってオプションとみなすべきでないかを知らせるも のである。この機能は bash のバージョン 2.01 で削除されたが、 GNU libc にはまだ残っている。

例
以下のソースコードは、 getopt_long() の使用法を、ほぼすべての機能について示したプログラムの例である。

#include <stdio.h>
int
main (argc, argv)
     int argc;
     char **argv;
{
  int c;
  int digit_optind = 0;
  while (1)
    {
      int this_option_optind = optind ? optind : 1;
      int option_index = 0;
      static struct option long_options[] =
      {
        {"add", 1, 0, 0},
        {"append", 0, 0, 0},
        {"delete", 1, 0, 0},
        {"verbose", 0, 0, 0},
        {"create", 1, 0, 'c'},
        {"file", 1, 0, 0},
        {0, 0, 0, 0}
      };
      c = getopt_long (argc, argv, "abc:d:012",
		       long_options, &option_index);
      if (c == -1)
	break;
      switch (c)
        {
        case 0:
          printf ("option %s", long_options[option_index].name);
          if (optarg)
            printf (" with arg %s", optarg);
          printf ("\n");
          break;
        case '0':
        case '1':
        case '2':
          if (digit_optind != 0 && digit_optind != this_option_optind)
            printf ("digits occur in two different argv-elements.\n");
          digit_optind = this_option_optind;
          printf ("option %c\n", c);
          break;
        case 'a':
          printf ("option a\n");
          break;
        case 'b':
          printf ("option b\n");
          break;
        case 'c':
          printf ("option c with value `%s'\n", optarg);
          break;
        case 'd':
          printf ("option d with value `%s'\n", optarg);
          break;
        case '?':
          break;
        default:
          printf ("?? getopt returned character code 0%o ??\n", c);
        }
    }
  if (optind < argc)
    {
      printf ("non-option ARGV-elements: ");
      while (optind < argc)
      printf ("%s ", argv[optind++]);
      printf ("\n");
    }
  exit (0);
}

バグ
このマニュアルページがごちゃごちゃしている。

POSIX.2 における getopt() の仕様、 POSIX.2 Interpretation 150 には技術的な問題がある。 GNU による実装では (おそらく他のすべての実装でも)、仕様と異なる正しい 動作を実装している。

準拠

getopt():
    環境変数 POSIXLY_CORRECT が設定されている場合は POSIX.2 に準拠。 他の場合は argv の要素は本当の意味での定数にはならない。なぜな ら順序が変更されてしまうからである。ただしそれらは、プロトタイプでは定数 であるかのようにしてある。これは他のシステムとの互換性のためである。