0
0

Rubyのoptparseライブラリを使ってオプション付きプログラムを実装しよう!

Last updated at Posted at 2023-10-13

はじめに

Ruby初心者がオプション付きのプログラムをゼロから自前で実装する場合かなり大変です。そんな時に大活躍してくれるがのoptparseライブラリです。オプション解析を良い感じにやってくれます。

最初に知っておくと良いこと

  • Rubyのoptparseは使用時にロードが必要なタイプの標準ライブラリで require "optparse"と書いてから使用します。
  • optparseの記事をインタネットで調べた際、ARGVとう変数によく出くわします。しかしARGVはoptparseとは直接は関係ありません。ARGVはRubyの特別な変数でコマンドライン引数を格納する配列となります。

実例を使ってoptparseを理解しよう!

  • 例として年と月を引数に取るカレンダープログラムを考えます。年のオプションを -y、月のオプションを -mとします。

例えば2023年10月のカレンダーを表示するプログラムなら下記のように記述するとします。

calendar.rb
ruby calendar.rb -y 2023 -m 10

calendar.rbを実行した際一体どのようにして 202310といった情報を取得できるのでしょうか?optparseを使うと簡単に202310といった情報を取得できます。

optparseの基本動作

  • 最小限の構成からなるプログラムをつかって基本的な仕組みを理解しましょう。プログラムと実行例を以下に記載します。
ruby calendar.rb -y 2023 -m 10
calendar.rb
require 'optparse'

opt = OptionParser.new

opt.on('-y') {|v| p v } 
opt.on('-m') {|v| p v } 

p ARGV # =>["-y", "2023", "-m", "10"]

opt.parse!(ARGV)
p ARGV # =>["2023", "10"]

p "#{ARGV[0]}年" # =>"2023年"
p "#{ARGV[1]}月" # =>"10月"

解説

require 'optparse'
optparseはRubyの組み込みライブラリではないのでこのように書いて使える状態にしてあげる必要があります。これがないと例えば次のOptionParserクラスを使うことができません。

opt = OptionParser.new
OptionParserクラスのnewメソッド使ってOptionParserクラスから作成されたインスタンスを作成。作成されたインスタンスをoptに格納しています。

opt.on('-y')
optのonメソッドの引数にオプションを指定します。ここでは、-yオプションを指定してます。こうすることで、-yがオプションとして認識されます。

{|v| p v }
コマンド引数に-yが渡された時、仮引数vにtrueが格納されます。(それ以外はfalseが格納されます)
このブロックでは、例として仮引数の値を返す処理が記述されています。

parse!メソッドでARGVが解析された時にonメソッドで指定したオプションが含まれていたらブロックの中身が実行されます。ここでは処理内容が設定されているだけで実行はされません。

opt.on('-m')
説明省略

一つ目の p ARGV
ARGVはコマンドライン引数が配列の要素として格納されています。例を見てもわかるように-y-mオプションも含め引数すべてが配列の要素として格納されています。

opt.parse!(ARGV)
optのparse!という破壊的メソッド使って配列ARGVを解析します。具体的にはonメソッドで指定した-y-mオプションを除いた引数を要素した配列をARGVに格納します。

二つ目の p ARGV
-yオプションが除かれ、2023, 10がARGVの要素として格納されています。

p "#{ARGV[0]}年" p "#{ARGV[1]}月"
無事年と月を取得することができました。

上のプログラムの問題点

とりあえず、年と月を取得することができました。でもこのプログラムには問題があります。
それはruby calendar.rb -m 10 -y 2023のようにオプションの順番を入れ替えて入力されてしまうと 10年2013月と表示されてしまうことです。どうすればよいのでしょうか?calendar.rbを次のように書き換えます。

calendar.rb
require 'optparse'

opt = OptionParser.new

options = {} # 追加
opt.on('-y year') { |y| options[:year] = y } # 変更
opt.on('-m month') { |m| options[:month] = m } # 変更

p ARGV # =>["-m", "10", "-y", "2023"]

opt.parse!(ARGV)
p ARGV # =>[]

p "#{options[:year]}年" # 変更 =>"2023年" 
p "#{options[:month]}月" # 変更 =>"10月"

解説

options = {}
空のハッシュを用意します。年と月の情報を管理する目的で使います。

opt.on('-y year') { |y| options[:year] = y }
onメソッドのオプション定義で末尾に何か(ここではyear)を書くと、仮引数yにはyearで指定した引数が入るようになります。
例えばruby calendar.rb -y 2023とした場合、仮引数yには2023が渡されます。
またさらにここでは後でこの値を参照できるようキー :year と値 2023 の組み合わせをoptionsハッシュに追加しています。

opt.on('-m month') { |m| options[:month] = m }
説明省略

p ARGV
onメソッドで指定した-y year-m monthオプションを除いた引数がARGVに格納されます。ruby calendar.rb -y 2023 -m 10の場合は、-y 2023 -m 10がオプションで指定された部分と解釈されるためARGVは最終的に空の配列となります。
(年月の情報はoptionsにて管理するため、この例でARGVは無用の長物です。)

p "#{options[:year]}年"
ハッシュにキー:yearを指定して2023を取得します。

p "#{options[:month]}月"
説明省略

以上で、ruby calendar.rb -y 2023 -m 10 と指定しても、
ruby calendar.rb -m 10 -y 2023 と指定しても無事同じ結果を得ることができるようになりました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0