OptionParser よりも指定が楽な ARGV.getopts のオプション指定（ロング/ショートも）

#まとめ
Ruby スクリプトの引数を `ARGV` だけで指定するのは簡便ですが、どの位置の引数が何に対応するのか直ぐに忘れてしまいますし、引数の省略も出来ないので面倒です。
標準ライブラリの `OptionParser` を使うのが手っ取り早いのですが、指定を詳細にしておかないといけないのがやはり面倒です。
で、楽なのが `ARGV.getopts` です。引数が `Hash` で返ってきます。しかも `--help` で受け付ける引数を表示させることも簡単にできます。
`ARGV.getopts` の使い方、特にショートネーム・ロングネームのオプション指定についてまとめました。

##1.ショートとロングと別々に
```ruby:getoptstest.rb
require 'optparse'
params = ARGV.getopts('abc:d:AB:C', 'alpha', 'brabo:', 'charlie:', 'delta:delta')
p params
```
```bash
$ 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` と表示されます。

```bash
$ 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` エラーになります。

```bash
$ ruby getoptstest.rb -a -c
getoptstest.rb:2:in `<main>': missing argument: -c (OptionParser::MissingArgument)
```
###オプション名の一部でも指定可能
```ruby:getoptstest_.rb
require 'optparse'
params = ARGV.getopts('abc:d:AB:C', 'alice', 'alpha', 'brabo:', 'charlie:', 'delta:delta')
p params
```
* オプション指定をロングの形式 `--` にした場合、オプションの全ての名称を指定しなくても、他のオプションと判別できれば指定を行うことが出来ます。 `getoptstest_.rb` の場合、 `alice` と `alpha` とは3文字目で判別できますので、 `alp` で `alpha` を指定していると判断してくれます。

```bash
$ 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` エラーになります。

```bash
$ ruby getoptstest_.rb --al
getoptstest_.rb:2:in `<main>': ambiguous option: --al (OptionParser::AmbiguousOption)
```

##2.ロングの1文字目をショート形式で指定
* ARGV.getopts の第1引数がショートの指定なので、ロングの形式のオプションの冒頭文字と衝突しない場合には、オプションの冒頭文字でオプションが指定できます。第1引数を空文字にしても問題なしです。

```ruby:getoptstest2.rb
require 'optparse'
params = ARGV.getopts('z', 'Alpha', 'brabo:', 'charlie:', 'delta:delta')
p params
```
```bash
$ 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"}
```
* ショートの形式なので、以下のようにオプションと引数との間の空白を省略した書式でも同じ結果が返ります。

```bash
$ 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` エラーになります。

```bash
$ ruby getoptstest2.rb -A -cCheck
getoptstest2.rb:2:in `<main>': invalid option: -A (OptionParser::InvalidOption)
```
* ショートの指定が大文字であれば、ショートの指定と同じアルファベットの小文字でロングのオプションを指定することが出来ます。

```ruby:getoptstest2_.rb
require 'optparse'
params = ARGV.getopts('AB', 'alpha', 'brabo:', 'charlie:', 'delta:delta')
p params
```
```bash
$ 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文字目が同じ場合
```ruby:getoptstest3.rb
require 'optparse'
params = ARGV.getopts('', 'alice', 'alpha', 'brabo:', 'charlie:', 'delta:delta')
p params
```

```bash
$ ruby getoptstest3.rb --alice
{"alice"=>true, "alpha"=>false, "brabo"=>nil, "charlie"=>nil, "delta"=>"delta"}
```
1文字目が同じ場合に、冒頭文字のショート形式でその文字を指定した場合には、どちらのオプションであるのか不明であるとして `OptionParser::AmbiguousOption` エラーになります。

```bash
$ ruby getoptstest3.rb -a
getoptstest3.rb:2:in `<main>': ambiguous option: -a (OptionParser::AmbiguousOption)
```
#返ってくる `Hash` の key を `Symbol` にしたい
```ruby
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](http://stackoverflow.com/questions/800122/best-way-to-convert-strings-to-symbols-in-hash)）
もちろん、一気にやっても問題ありません。

```ruby:getoptstest.rb
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
```

```bash
$ 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.
>```ruby
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
```
###長いオプションも使いたいんだけど

>```ruby
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’)には、デフォルト値も指定できます。

>##コメント欄：長いオプションの省略

>```ruby
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](http://qiita.com/genta/items/785900055a5be2ba5d2c)


2.
>```
require "optparse"
options = ARGV.getopts("", "dry-run")
p options
```
実行結果

>```
$ ruby temp.rb --dry-run
{"dry-run"=>true}
$ ruby temp.rb
{"dry-run"=>false}
```
>[Rubyのoptparseを軽く使うなら悩む必要なんてなかった - Qiita](http://qiita.com/ionis_h/items/5433dc38c154a30dd450)

##るりまも見てみる
>###ARGV の機能
`optparse` を `require` すると `ARGV` に `OptionParser::Arguable` の機能 が加わります。以下の書き方ができるようになります。 `OptionParser::Arguable#getopts` はオプションを保持した `Hash` を返します。
>[library optparse](http://rurema.clear-code.com/1.9.3/library/optparse.html#argv)

##ロングとショートの区別はどこで
るりまにちゃんと書いてありました。

>###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` のサブクラスの例外になります。
例:

>```ruby
# 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` を使うことが出来ます。