はじめに
library optparse (Ruby 3.1 リファレンスマニュアル)に記載してある
require 'optparse' opt = OptionParser.new opt.on('-a') {|v| p v } opt.on('-b') {|v| p v } # parse() の場合、ARGVは変更されない。 # オプションを取り除いた結果は argv に設定される。 argv = opt.parse(ARGV) p argv
を理解するために、optparseの基本をまとめました。
opt.on('-X') { ブロック処理 }
ARGV
opt.parse(ARGV)
/opt.parse!(ARGV)
の3点が分かれば土台的な部分の理解はOKだと思うので、これらについて記事を書きます。
間違っている部分がありましたら是非ご指摘ください。
opt.on('-X') { ブロック処理 }
を理解する
opt.on('-a') {|v| p v } opt.on('-b') {|v| p v }
引数をオプションとして登録します。 なお、この段階ではブロックの処理は行われません。
longオプションや、help時に記載される説明も、ここのメソッドで定義することが出来ますが、あくまで「オプションの登録」と「ブロックは実行されない」ことを意識していればOKだと思います。
ブロックの処理は、後述する opt.parse(ARGV)
/ opt.parse!(ARGV)
で実行されます。
ARGV
を理解する
ARGV
には、スクリプト実行時に利用したオプションと、その引数を文字列要素として格納した配列が代入されています。
実際に簡単なコードを書いて確認してみたいと思います。
# opt.rb require 'optparse' opt = OptionParser.new opt.on('-a') {|va| p va} opt.on('-b') {|vb| p vb} p ARGV
# 実行結果 ❯ ruby opt.rb -a foo -b bar hoge ["-a", "foo", "-b", "bar", "hoge"]
- オプション: -a, -b
- 引数: (-a) foo, (-b) bar hoge
を渡して、最後にARGV
を表示させる処理を書いてみたところ、このような実行結果になりました。
このことから、オプション・引数を文字列とした要素を持つ配列がARGVに代入されていることが確認できます。
opt.parse(ARGV)
/ opt.parse!(ARGV)
を理解する
OptionParseクラスのparse
メソッドは、ARGV
から、オプションの要素を取り除いたものを戻り値とするメソッドとなります。
また、opt.onのブロックの実行も行います。
こちらも実行結果を確認したいと思います。
# opt.rb require 'optparse' opt = OptionParser.new opt.on('-a') {|va| p va} opt.on('-b') {|vb| p vb} parse = opt.parse(ARGV) p parse
# 実行結果 ❯ ruby opt.rb -a foo -b bar hoge true true ["foo", "bar", "hoge"]
実行結果を見ると、true
という表示が2行続けて並んでいます。これが、opt.on
メソッドのブロック内の処理となります。
parse
メソッドを呼び出したタイミングで、ブロックの処理が行われていることが分かります。
また、戻り値を確認するためのp parse
の結果を見ると、ARGVからオプションの要素のみが取り除かれた配列が表示されています。
parse!
の場合
破壊的なメソッドになります。
そのため、ARGV
からもオプションの要素を除外してしまいます。
# parse!に変え、ARGVを見てみる parse = opt.parse!(ARGV) p ARGV
# 実行結果 ❯ ruby opt.rb -a foo -b bar hoge true true ["foo", "bar", "hoge"]
ARGV
には本来、オプションも引数も両方格納されているはずですが、parse!
の破壊的メソッドによってオプションが取り除かれていることが分かります。
なぜtrueという表示をするのか?
もう一度ここで、opt.on
メソッドのブロックを見てみます。
opt.on('-a') {|va| p va} opt.on('-b') {|vb| p vb}
実はブロックパラメータには、オプションを使用したか否かのBooleanオブジェクトが渡されています。
今回は、-a
-b
共にオプションとして指定していたため、どちらもtrue
が各パラメータに渡されています。
そのため、一方のオプションを指定しないと、下記のように指定した方のtrue
のみが表示されます。
❯ ruby opt.rb -a true
結合したオプション(-ab
や-alr
など)の場合
# opt.rb require 'optparse' opt = OptionParser.new opt.on('-a') {|va| p va} opt.on('-b') {|vb| p vb} opt.on('-c') {|vc| p vc} opt.parse(ARGV)
# 実行結果 ❯ ruby opt.rb -abc true true true
御覧の通り、オプションを-abc
と連結して渡しても、各ブロックパラメータにはtrueが渡されています。
連結しても、バラバラで書いてもしっかりとオプションは渡せるようです。
最後に
オプションの理解が浅かったため、基本的な部分をまとめました。 リファレンスだけでは把握するのは難しいため、実験的に色々自分で実行してみるのが一番良いですね。