首页 > 解决方案 > 使用 OptParser 在 Ruby 脚本中访问命令行选项文字

问题描述

我想在解析之前访问传递给 Ruby 脚本的命令行选项的文字文本。

这是一个示例(只是一个简化的示例,以使问题更清楚——这不是“我的代码”),这将使这一点更清楚:

require 'optparse'

options = {}
OptionParser.new do |opts|
  opts.banner = "Usage: example.rb [options]"

  opts.on("-s", "--start", "Enter start date for the data you want from the API") do |start_date|
    options[:start_date] = start_date
  end
  opts.on("-e", "--end", "Enter the end date for the data you want from the API") do |end_date|
    options[:end_date] = end_date
  end
  opts.on("-w", "--window", "Enter a number of days back in time to look prior to today") do |window|
    options[:start_date] = window.days.ago
    options[:end_date] = Time.zone.today
  end
  opts.on("-a", "--all", "Get all historical data since the beginning of time (as recorded in the API's database)") do |all_time|
    options[:start_date] = Date.parse("1900-01-01")
    options[:end_date] = Time.zone.today
  end
  raise "You can't define an end date and not a start date" if command_line_options & %w[-e --end] && !(command_line_options & %w[-s --start])
  raise "Please use only one type of temporal option." if (command_line_options & %w[-a --all -w --window -e --end]).count > 1
end.parse!

这里的raise线条显示了我想要完成的事情。看看command_line_options那些线。在示例脚本中,那些没有价值。我该如何设置它们?

请注意,无论用户使用--startand--end--windowor --alloption[:start_date]andoption[:end_date]都被设置。我为用户提供了 3 种不同的方法来设置开始日期和结束日期,但我想确保它们不会混合和匹配这些。但为了进行此输入验证并确保用户输入了合理的值,我希望能够访问原始未解析的命令行开关。我怎样才能做到这一点?

我意识到还有其他方法可以实现我的目标,但我所描述的似乎应该很容易实现,而且它似乎是最干净的做事方式。

标签: rubyoptparse

解决方案


这是不可能的。此外,您的代码有太多故障,无需担心完成错误输入报告的最佳方法。

  1. 所有参数都以字符串形式出现
  2. 没有方法Time.zone
  3. 参数化选项将使用参数就地指定
  4. 没有days在字符串上声明方法(也没有在整数上),这都是废话

总而言之,这是工作版本。

require 'optparse'
require 'date'

options = Hash.new { |h, k| h[k] = [] }
OptionParser.new do |opts|
  opts.banner = "Usage: example.rb [options]"

  opts.on("-sSTART", "--start=START", "Enter start date for the data you want from the API") do |start_date|
    options[:start_date] << Date.parse(start_date)
  end
  opts.on("-eEND", "--end=END", "Enter the end date for the data you want from the API") do |end_date|
    options[:end_date] << Date.parse(end_date)
  end
  opts.on("-wWINDOW", "--window=WINDOW", "Enter a number of days back in time to look prior to today") do |window|
    options[:start_date] << Date.today - Integer(window)
    options[:end_date] << Date.today
  end
  opts.on("-aALL", "--all=ALL", "Get all historical data since the beginning of time (as recorded in the API's database)") do |all_time|
    options[:start_date] << Date.parse("1900-01-01")
    options[:end_date] << Date.today
  end
end.parse!

case options.map(&:last).map(&:size)
when [1, 1] then :ok
when [], [1] then raise "You must define both dates"
else raise "Please use only one type of temporal option"
end

options = options.map { |k, v| [k, v.first] }.to_h
puts options

推荐阅读