我尝试使用OptionParser创建包含子命令的命令行程序。我跟随" ruby's OptionParser to get subcommands"。
问题在于它不允许这样的用例:
ruby main.rb --version
#=> main.rb in `<main>': undefined method `order!' for nil:NilClass (NoMethodError)
但它确实允许这样做:
ruby main.rb foo --options
ruby main.rb --options foo
ruby main.rb --options foo --options
在没有给出子命令的情况下,如何正确处理命令行参数。
我的示例代码是:
global = OptionParser.new do |opts|
opts.banner = "Usage: opt.rb [options] [subcommand [options]]"
opts.on("-v", "--version", "Print the version") do |v|
options[:version] = v
end
opts.separator ""
opts.separator subtext
end
答案 0 :(得分:1)
也许这会有所帮助:
require 'optparse'
VERSION = '1.0.0'
options = {}
OptionParser.new do |opt|
opt.on('-f', '--foo', 'Foo it') { |o| options[:foo] = o }
opt.on_tail('-v', '--version') do
puts VERSION
exit
end
end.parse!
puts options
将其另存为&#34; test.rb&#34;并使用ruby test.rb
运行它返回:
{}
使用ruby test.rb -f
或--foo
运行它会返回:
{:foo=>true}
使用ruby test.rb -v
或--version
运行它会返回:
1.0.0
为了获得更多乐趣,请运行ruby test.rb -h
或--help
返回:
Usage: test [options]
-f, --foo Foo it
即使我没有定义-h
或--help
。
如果我希望-v
和--version
标记显示在列表中,那么我将它们从on_tail
方法更改为普通on
方法:
require 'optparse'
VERSION = '1.0.0'
options = {}
OptionParser.new do |opt|
opt.on('-f', '--foo', 'Foo it') { |o| options[:foo] = o }
opt.on('-v', '--version', 'Returns the version') do
puts VERSION
exit
end
end.parse!
puts options
会返回:
Usage: test [options]
-f, --foo Foo it
-v, --version Returns the version
我可以补充一下:
puts ARGV
到脚本的末尾,看到OptionParser正确处理标志和参数:
>ruby test.rb bar --foo
{:foo=>true}
bar
>ruby test.rb --foo bar
{:foo=>true}
bar
参见&#34; Pass variables to Ruby script via command line&#34;了解更多信息。
您的示例代码无法使用--options
处理您的示例输入。没有定义--options
的处理程序。也不是subtext
。您的代码返回:
undefined local variable or method `subtext' for main:Object (NameError)
将块剥离到:
global = OptionParser.new do |opts|
opts.on("-v", "--version", "Print the version") do |v|
options[:version] = v
end
end
再次运行返回:
invalid option: --options (OptionParser::InvalidOption)
所以,再一次,你的例子并不符合你所说的结果。
答案 1 :(得分:1)
包含错误的行:
global.order!
command = ARGV.shift
subcommands[command].order!
如果global.order!
使用全部ARGV
,则命令为nil
。所以......检查一下。
global.order!
command = ARGV.shift
unless command
STDERR.puts "ERROR: no subcommand"
STDERR.puts global # prints usage
exit(-1)
end
subcommands[command].order!