#まとめ
Ruby スクリプトの引数を ARGV
だけで指定するのは簡便ですが、どの位置の引数が何に対応するのか直ぐに忘れてしまいますし、引数の省略も出来ないので面倒です。
標準ライブラリの OptionParser
を使うのが手っ取り早いのですが、指定を詳細にしておかないといけないのがやはり面倒です。
で、楽なのが ARGV.getopts
です。引数が Hash
で返ってきます。しかも --help
で受け付ける引数を表示させることも簡単にできます。
ARGV.getopts
の使い方、特にショートネーム・ロングネームのオプション指定についてまとめました。
##1.ショートとロングと別々に
require 'optparse'
params = ARGV.getopts('abc:d:AB:C', 'alpha', 'brabo:', 'charlie:', 'delta:delta')
p params
$ ruby getoptstest.rb -a -don --charlie Check
{"a"=>true, "b"=>false, "c"=>nil, "d"=>"on", "A"=>false, "B"=>nil, "C"=>false, "alpha"=>false, "brabo"=>nil, "charlie"=>"Check", "delta"=>"delta"}
- ARGV.getopts の第1引数がショートネームの指定、それ以降がロングネームの指定です。
- キーはシンボルではなく文字列です。シンボルにしたい場合には
ARGV.getopts(…)
の部分をHash[ARGV.getopts(…).map { |k, v| [k.to_sym, v] }]
としましょう。 - ショートの各文字に
:
を付けると引数を取ります。大文字と小文字は別扱いです。 - ロングでも末尾に
:
を付けると引数を取ります。ロングはデフォルト値を取ることが出来ます。 - 引数に
--help
を渡すと簡単なヘルプ画面が返されます。引数が必要な場合にはVAL
と表示されます。
$ ruby getoptstest.rb --help
Usage: getoptstest [options]
-a
-b
-c VAL
-d VAL
-A
-B VAL
-C
--alpha
--brabo VAL
--charlie VAL
--delta VAL
- なお、引数を取らないオプションは
boolean
なので値はtrue / false
になります。 - 引数を取るオプションは指定しないと値が
nil
になります。また、オプションを指定したときに引数を付けないとOptionParser::MissingArgument
エラーになります。
$ ruby getoptstest.rb -a -c
getoptstest.rb:2:in `<main>': missing argument: -c (OptionParser::MissingArgument)
###オプション名の一部でも指定可能
require 'optparse'
params = ARGV.getopts('abc:d:AB:C', 'alice', 'alpha', 'brabo:', 'charlie:', 'delta:delta')
p params
- オプション指定をロングの形式
--
にした場合、オプションの全ての名称を指定しなくても、他のオプションと判別できれば指定を行うことが出来ます。getoptstest_.rb
の場合、alice
とalpha
とは3文字目で判別できますので、alp
でalpha
を指定していると判断してくれます。
$ ruby getoptstest_.rb --alp
{"a"=>false, "b"=>false, "c"=>nil, "d"=>nil, "A"=>false, "B"=>nil, "C"=>false, "alice"=>false, "alpha"=>true, "brabo"=>nil, "charlie"=>nil, "delta"=>"delta"}
判別出来ない場合には OptionParser::AmbiguousOption
エラーになります。
$ ruby getoptstest_.rb --al
getoptstest_.rb:2:in `<main>': ambiguous option: --al (OptionParser::AmbiguousOption)
##2.ロングの1文字目をショート形式で指定
- ARGV.getopts の第1引数がショートの指定なので、ロングの形式のオプションの冒頭文字と衝突しない場合には、オプションの冒頭文字でオプションが指定できます。第1引数を空文字にしても問題なしです。
require 'optparse'
params = ARGV.getopts('z', 'Alpha', 'brabo:', 'charlie:', 'delta:delta')
p params
$ ruby getoptstest2.rb --help
Usage: getoptstest2 [options]
-z
--Alpha
--brabo VAL
--charlie VAL
--delta VAL
$ ruby getoptstest2.rb -ac Check
{"z"=>false, "Alpha"=>true, "brabo"=>nil, "charlie"=>"Check", "delta"=>"delta"}
- ショートの形式なので、以下のようにオプションと引数との間の空白を省略した書式でも同じ結果が返ります。
$ ruby getoptstest2.rb -acCheck
{"z"=>false, "Alpha"=>true, "brabo"=>nil, "charlie"=>"Check", "delta"=>"delta"}
$ ruby getoptstest2.rb -a -cCheck
{"z"=>false, "Alpha"=>true, "brabo"=>nil, "charlie"=>"Check", "delta"=>"delta"}
- ショートの形式で指定できるのは小文字のみです。ロングで冒頭が大文字であってもショートの形式の場合には小文字で指定します。大文字にすると
OptionParser::InvalidOption
エラーになります。
$ ruby getoptstest2.rb -A -cCheck
getoptstest2.rb:2:in `<main>': invalid option: -A (OptionParser::InvalidOption)
- ショートの指定が大文字であれば、ショートの指定と同じアルファベットの小文字でロングのオプションを指定することが出来ます。
require 'optparse'
params = ARGV.getopts('AB', 'alpha', 'brabo:', 'charlie:', 'delta:delta')
p params
$ ruby getoptstest2_.rb -a
{"A"=>false, "B"=>false, "alpha"=>true, "brabo"=>nil, "charlie"=>nil, "delta"=>"delta"}
$ ruby getoptstest2_.rb -A
{"A"=>true, "B"=>false, "alpha"=>false, "brabo"=>nil, "charlie"=>nil, "delta"=>"delta"}
$ ruby getoptstest2_.rb -Aa
{"A"=>true, "B"=>false, "alpha"=>true, "brabo"=>nil, "charlie"=>nil, "delta"=>"delta"}
$ ruby getoptstest2_.rb -aA
{"A"=>true, "B"=>false, "alpha"=>true, "brabo"=>nil, "charlie"=>nil, "delta"=>"delta"}
##3.ロングの1文字目が同じ場合
require 'optparse'
params = ARGV.getopts('', 'alice', 'alpha', 'brabo:', 'charlie:', 'delta:delta')
p params
$ ruby getoptstest3.rb --alice
{"alice"=>true, "alpha"=>false, "brabo"=>nil, "charlie"=>nil, "delta"=>"delta"}
1文字目が同じ場合に、冒頭文字のショート形式でその文字を指定した場合には、どちらのオプションであるのか不明であるとして OptionParser::AmbiguousOption
エラーになります。
$ ruby getoptstest3.rb -a
getoptstest3.rb:2:in `<main>': ambiguous option: -a (OptionParser::AmbiguousOption)
#返ってくる Hash
の key を Symbol
にしたい
params.inject({}) { |hash,(k,v)| hash[k.to_sym] = v; hash }
で Symbol
の key になります。
(参考:ruby - Best way to convert strings to symbols in hash - Stack Overflow)
もちろん、一気にやっても問題ありません。
require 'optparse'
params = ARGV.getopts('abc:d:AB:C', 'alpha', 'brabo:', 'charlie:', 'delta:delta').inject({}) { |hash,(k,v)| hash[k.to_sym] = v; hash }
p params
$ ruby etc/getoptstest.rb -a -don --charlie Check
{:a=>true, :b=>false, :c=>nil, :d=>"on", :A=>false, :B=>nil, :C=>false, :alpha=>false, :brabo=>nil, :charlie=>"Check", :delta=>"delta"}
#引用・解説など(だらだらとw)
Ruby でスクリプトに渡される引数配列 ARGV
を OptionParser
を扱うのは…いろいろ準備が面倒です。
で、簡単にする方法については先人が Qiita にいろいろと投稿してくださっています。
1.
require 'optparse'
params = ARGV.getopts('abc:')
p params
>```bash
% ./its_the_ruby_way.rb -a -c /tmp/file
{"a"=>true, "b"=>false, "c"=>"/tmp/file"}
% ./its_the_ruby_way.rb -h
Usage: its_the_ruby_way [options]
-a
-b
-c VAL
###長いオプションも使いたいんだけど
require 'optparse'
params = ARGV.getopts('abc:', 'alpha', 'brabo', 'charlie:/tmp/default_file')
p params
>```
% ./its_the_ruby_way.rb --alpha -c /tmp/hoge
{"a"=>false, "b"=>false, "c"=>"/tmp/hoge", "alpha"=>true, "brabo"=>false, "charlie"=>"/tmp/default_file"}
長い版のオプション(‘--charlie’)には、デフォルト値も指定できます。
##コメント欄:長いオプションの省略
require 'optparse'
params = ARGV.getopts('', 'alpha', 'brabo', 'charlie:/tmp/default_file')
p params
>```
./argv.rb -ab -c hoge
{"alpha"=>true, "brabo"=>true, "charlie"=>"hoge"}
Ruby - ARGVの処理にOptionParserを使ってるライバルをバックミラーから高速に消し去るARGV.getoptsの使い方 - Qiita
require "optparse"
options = ARGV.getopts("", "dry-run")
p options
実行結果
>```
$ ruby temp.rb --dry-run
{"dry-run"=>true}
$ ruby temp.rb
{"dry-run"=>false}
##るりまも見てみる
###ARGV の機能
optparse
をrequire
するとARGV
にOptionParser::Arguable
の機能 が加わります。以下の書き方ができるようになります。OptionParser::Arguable#getopts
はオプションを保持したHash
を返します。
library optparse
##ロングとショートの区別はどこで
るりまにちゃんと書いてありました。
###instance method OptionParser::Arguable#getopts
getopts(short_opt, *long_opt)
->Hash
指定された short_opt や long_opt に応じて自身をパースし、結果を Hash として返します。
コマンドラインに - もしくは -- を指定した場合、それ以降の解析を行ないません。
[PARAM]short_opt
:
ショートネームのオプション(-f や -fx)を文字列で指定します。オプションが -f と -x の 2つの場合は "fx" の様に指定します。ここでオプションがないときは空文字列を指定します。 オプションが引数をとる場合は直後に ":" を付けます。
[PARAM]long_opt
:
ロングネームのオプション(--version や --bufsize=512)を文字列で指定をします。 オプションが引数をとる場合は後ろに ":" を付けます。 オプションの引数のデフォルト値を ":" の直後に指定することができます。 例えば、"bufsize:1024" となります。
[EXCEPTION]OptionParser::ParseError
:
自身のパースに失敗した場合、発生します。 実際はOptionParser::ParseError
のサブクラスの例外になります。
例:
t.rb の内容
require 'optparse'
params = ARGV.getopts("ab:", "foo", "bar:", "bufsize:1024")
p params
実行結果
$ ruby t.rb -b 1 --foo --bar xxx -- -a
{"bufsize"=>"1024", "a"=>false, "b"=>"1", "foo"=>true, "bar"=>"xxx"} # "a"=>false であることに注意。
>[instance method OptionParser::Arguable#getopts](http://rurema.clear-code.com/1.9.3/method/OptionParser=3a=3aArguable/i/getopts.html)
この `OptionParser::Arguable` モジュールは `require 'optparse'` により `ARGV` に extend されます。ですので、 `ARGV.getopts` で `OptionParser::Arguable#getopts` を使うことが出来ます。