2015年12月26日土曜日

RubyのOptionParserで地味にはまった

今まで動いていたのに、オプションを増やしたら謎の挙動をして、数時間を無駄にしたのでメモ。

Rubyでコマンドライン引数処理をするのに、optparseを使う人が多いと思います。

こんな感じで使います。

require "optparse"
opts = OptionParser.new
# 引数
opts = OptionParser.new
instance_type = nil
opts.on("-t","--instance_type INSTANCE_TYPE") do |type|
  pp type
  instance_type = type
end
# よく忘れるパーズ実行
opts.parse!(ARGV)
これで、たとえば
ruby hoge.rb -t t2.small
見たいにすると、instance_type変数にt2.smallという値が入ります。
opts.onの第一引数にはショートオプションを、第二引数にはロングオプションとオプションの説明を入れます。
--からはじめるとロングオプションとして認識します。
ロングオプションはどのオプションか一意に決まる長さまで指定すれば良いです。

で、ここでオプションを増やします。
private_ip = nil
opts.on("-ip","--private_ip PRIVATE_IP_ADDRESS") do |ip|
  pp ip
  private_ip = ip
end
さて、これは正しく動作しません(笑)
ruby hoge.rb -ip 192.168.0.1
としても、private_ipには何故か"p"という文字が入ります。
ruby hoge.rb --private_ip 192.168.0.1
だと正しく動き、private_ipには"192.168.0.1"という文字が入ります。
大抵デバック時には引数を埋め込むため気づきませんでしたが、
ショートオプションはアルファベット1文字しか有効ではなく、それ以降の文字列は引数と認識されます。

なので、
private_ip = nil
opts.on("-i","--private_ip PRIVATE_IP_ADDRESS") do |ip|
  pp ip
  private_ip = ip
end
と同じ挙動になり、-ipというオプションは-iオプションに引数pを渡していることになります。

え?常識(汗

よく見たらマニュアルにちゃんと書いてありましたね(汗

ショートオプションの引数指定は使いにくいので、このような場合はロング オプションの方が使う方もわかりやすいです。例えば、上記の場合、-ab を 指定すると -a b と解釈されます。-a が引数を持たない最初の例なら -a -b と 解釈されます。






0 件のコメント:

コメントを投稿