8tako8tako8’s blog

ソフトウェアエンジニア

Rubyのoptparseを使ったコマンドライン引数の解析

はじめに

Rubyの標準ライブラリであるoptparseは、コマンドライン引数の解析を簡単かつ効率的に行うためのライブラリです。optparseの基本的な機能について説明し、使い方を紹介します。

基本的な使い方

使用するために、optparseを読み込みます。

require 'optparse'

onメソッドでオプションを定義します。また、どのオプションが指定されたかを保持するためにハッシュを使用します。

opt = OptionParser.new
option = {}
opt.on('-f', '--file FILENAME', 'input file') { |v| option[:f] = v }
opt.on('-m', '--month MONTH', 'input the month(1-12)') { |v| option[:m] = v }
opt.parse(ARGV)

puts "-f:#{option[:f]}, -m:#{option[:m]}"

上記のコードを実行するとコマンドライン引数を受け取れていることがわかります。

$ ruby optparse.rb -f input_file -m 1
-f:input_file, -m:1

定義されているオプションも簡単に出力できます

opt.on('-h', '--help', 'Show help message') { puts opt }

カレンダーを作る

Rubyでカレンダーを作成するのにoptparseを使ってオプション-mを実装しました。

# オプションなし
$ ruby calendar.rb
      4月 2023
月 火 水 木 金 土 日
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

# オプションで1月を指定
$ ruby calendar.rb -m 1
      1月 2023
月 火 水 木 金 土 日
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

なお、コードは下記になります。

require 'date'
require 'optparse'

def print_calendar(month = nil)
  year = Time.now.year # 現在の年
  month ||= Time.now.month # nilなら現在の月
  first_day = Date.new(year, month, 1) # 始まり
  last_day = Date.new(year, month, -1) # 終わり

  print_header(month, year)
  print_first_spaces(first_day.wday)

  (first_day..last_day).each do |date|
    print date.strftime('%e')
    print(date.sunday? || date == last_day ? "\n" : ' ')
  end
end

def print_header(month, year)
  puts "      #{month}#{year}"
  puts '月 火 水 木 金 土 日'
end

def print_first_spaces(wday)
  if wday.zero? # 日
    print '                  '
  elsif wday == 1 # 月
    print ''
  else # 火〜土
    print '   ' * (wday - 1)
  end
end

def valid_month(month)
  month && (month >= 1 && month <= 12)
end

# コマンドライン引数を取得
opt = OptionParser.new
option = {}
opt.on('-m MONTH', 'the month(1-12)') { |v| option[:m] = v }
opt.parse(ARGV)
target_month = option[:m]&.to_i

# オプションのチェック
if target_month && !valid_month(target_month)
  puts "#{target_month} is neither a month number (1..12) nor a name"
  return
end

# 出力
if target_month
  print_calendar(target_month)
else
  print_calendar
end

まとめ

optparseは、オプションの定義やヘルプメッセージの生成が容易に行えるため、コマンドラインツールやスクリプトを開発する際に非常に便利です。ぜひ使ってみてください。