roptは、Ruby用の簡単で実用的なコマンドラインオプション解析ライブラリです。 GNU getopt に似た文法でオプションの仕様を定義できます。
ファイルは lib/ropt.rb だけですが、一応インストーラが付いています。 以下のコマンドでインストールされます。
% ruby install.rb config % ruby install.rb setup % ruby install.rb install
添付のスクリプト example.rb を例に取ります。このスクリプトは以下のコマンドラインオプションを受け付けます。
def usage
STDERR.puts("\
Usage: #{File.basename($0)} [OPTION]... ARG1 ARG2
Options
-a 短いオプション/引数無し
-b ARG 短いオプション/引数あり
-c ARG 短いオプション/引数あり&複数回指定可能
--long-a 長いオプション/引数無し
--long-b ARG 長いオプション/引数あり
--long-c ARG 長いオプション/引数あり&複数回指定可能
")
exit 1
end
まず、 ROpt.parse で引数を解析し、結果を得ます。 失敗時にはnilが返ります。 その場合usageメソッドを呼び出し、文法を表示します。
require "ropt" opt = ROpt.parse(ARGV, "ab:c::", "long-a", "long-b:", "long-c::") || usage
opt の [] メソッドでオプションの値を得られます。
puts("-a specified.") if opt[:a]
puts("-b is #{opt[:b].inspect}") if opt[:b]
puts("-c are #{opt[:c].inspect}") unless opt[:c].empty?
puts("--long-a specified.") if opt['long-a']
puts("--long-b is #{opt['long-b'].inspect}") if opt['long-b']
puts("--long-c are #{opt['long-c'].inspect}") unless opt['long-c'].empty?
また、 args メソッドで残りの引数を得られます。
puts("Rest arguments: #{opt.args.inspect}") unless opt.args.empty?
適当な引数を与えて実行してみましょう。
% ruby example.rb -ab B -c C1 -c C2 --long-a --long-b B --long-c C1 -- 1 2 3 -a specified. -b is "B" -c are ["C1", "C2"] --long-a specified. --long-b is "B" --long-c are ["C1"] Rest arguments: ["1", "2", "3"]
誤った引数を与えれば文法が表示されます。
% ruby example.rb --unknown Usage: example.rb [OPTION]... ARG1 ARG2 Options -a Short option / Without argument -b ARG Short option / With argument -c ARG Short option / With argument, multiple options allowed. --long-a Long option / Without argument --long-b ARG Long option / With argument --long-c ARG Long option / With argument, multiple options allowed.
ROpt.parse にブロックを与えると、 仕様に定義されているもの以外のオプションが現れたときの処理を記述できます。
添付のスクリプト example2.rb がその例です。
require "ropt"
opt = ROpt.parse(ARGV, nil, "static") { |option, argv|
if %r"^dynamic" =~ option
puts("Dynamic option --#{option} with argument `#{argv.shift}'.")
true
else
STDERR.puts("Unkown option: `#{option}'")
exit 1
end
}
puts("--static.") if opt[:static]
これは --dynamicXXX というオプションを、すべて引数付きオプションとして受け付けます。 それ以外はエラーを出力して終了します。
% ./example2.rb --static --dynamic1 arg Dynamic option --dynamic1 with argument `arg'. --static. % ./example2.rb --unknown Unkown option: `unknown'
ブロックの引数については、リファレンスの ROpt.parse を参照してください。
ROpt.parse(argv, short_option_spec, *long_option_spec, ...)
ROpt.parse(argv, short_option_spec, *long_option_spec, ...) { |option, argv| ...}コマンドライン引数の配列argvを解析し、 解析結果を格納したROpt::ParseResultオブジェクトを返します。 不明なオプションを含むなどの文法エラーを検出した場合には、 解析を中断してnilを返します。
short_option_specには短いオプションとして受け付ける文字を以 下のように一つ以上指定します。
"a" => -a(引数無し)"a:" => -a(引数あり)"a::" => -a(引数あり/複数回指定可能)"a:b" => -a(引数あり), -b(引数無し)nil または "" => 短いオプション無しlong_option_specには長いオプションとして受け付ける文字列を、 以下のように列挙します。
"long" => --long(引数無し)"long:" => --long(引数あり)"long::" => --long(引数あり/複数回指定可能)"long::", "long2" => --long(引数あり/複数回指定可能), --long2(引数無し)どちらの場合も、引数があっても無くてもよいオプションは定義できません。
また、getoptsのようにデフォルト値は指定できません。
不正な文字列をshort_option_spec, long_option_specに渡すと、
例外InvalidParseRuleErrorが発生します。
ブロックを渡すと、想定外のオプションが現れた場合の処理を記述できます。 ブロックの引数optionにはオプションの文字列が、 argvにはそのオプション以降の引数の配列が渡されます。
ブロックの中では、場合に応じて以下の処理を行って下さい。
ROpt.parseによって返される、解析結果を格納したオブジェクトです。 オプションの有無や引数、オプションでは無い残りの引数を取得することができます。
ROpt::ParseResult#[option]オプションoption(文字列もしくはSymbol)の状態を返します。 オプションの状態によって以下の値が返ってきます。
optionが仕様外のオプションだった場合には、例外IndexErrorが発生します。
これは、仕様を定義し忘れるミスを防ぐためです。
ちなみに、optionに整数を渡すと ROpt::ParseResult#args[option]と同じ意味になります。
ROpt::ParseResult#argsこのオブジェクトが保持する、オプションでは無い残りの引数の配列を返します。
ROpt::ParseResult#optionsこのオブジェクトが保持する、オプションの状態を格納するハッシュを返します。 通常オプションの状態を得るには、 ROpt::ParseResult#[option]を使います。
Rubyと同じライセンスの下で、自由に利用できます。 要望やバグレポートは 白井 薫 <shirai@korinkan.co.jp> までお願いします。