使用OptionParser在Ruby中解析多个命令行选项

6

我刚开始使用Ruby的OptionParser,并且想要使用可以使用不止一个参数的标志。

例如,我想能够运行:

script --move src dst

请注意,srcdst之间没有用逗号分隔。
我的最初想法是:
opts.on("-m src dst", "--move src dst ", "move file from SRCto DST") do |src|
    # do something
end

但这并没有起作用。我认为这不是正确的方法。但是该如何做呢?


文档中有一个非常好的例子,网址是http://ruby-doc.org/stdlib-2.2.4/libdoc/optparse/rdoc/OptionParser.html,在“生成帮助”标题下,展示了如何接受一个名为“name”的参数。同样的方法可以扩展到你的“src”和“dst”的情况。你需要重复示例中针对“name”的操作 - 分别为“src”和“dst”编写两个单独的“opts.on”语句。 - Wand Maker
3
OP特别询问如何接受同一选项的连续两个值。 - Jordan Running
2个回答

3
OptionParser的“完整示例”部分中,有一个例子详细说明了如何接受项目列表。
以下是基于该示例的示例程序。 opts.on中的第三个参数 Array 表示应使用输入 src,dst 创建数组。 要运行此示例,您需要执行 gem install trollop
# test.rb
require 'optparse'

options = {}
OptionParser.new do |opt|
  opt.on("-m src, dst", "--move src, dst", Array, "Move from src to dst") do |list|
    options[:src] = list[0]
    options[:dst] = list[1]
  end
end.parse!

puts options # It's a hash of parsed options

示例运行:

> ruby test.rb -m from,to
{:src=>"src", :dst=>"dst"}

>ruby test.rb -h
Usage: test [options]
    -m, --move src, dst              Move from src to dst

上述脚本强制使用逗号分隔选项。
如"Ruby中真正便宜的命令行选项解析"所示,似乎有一个gem包,trollop,可以用于命令行解析,并且非常容易使用。
下面给出了一个基于Trollop的示例程序,允许使用空格来指定具有多个值的选项。
# test.rb

require "trollop"

opts = Trollop::options do
  banner "Command line parsing using Trollop"
  opt :move, "--move src dst', Move from src to dst", :short => "-m", :long => "--move", :type => :strings
end
# An array of option values
p opts.move

运行示例:

>ruby test.rb -m hello world
["hello", "world"]

>ruby test.rb -h
Command line parsing using Trollop
  -m, --move=<s+>    '--move src dst', Move from src to dst
  -h, --help         Show this message

两种方法的帮助输出之间存在微妙的差异。Trollop产生的帮助文本中,--move=<s+>并没有明确指出它需要接受两个值,因此我不得不重复命令语法描述。

非常感谢,我从今天开始使用这种格式。你认为有没有什么办法可以去掉逗号呢?这样,代替--move src, dst... 你只需写--move src dst... 不管怎样,还是谢谢 :) - Daniel Hernandez
我正在努力弄清楚这个问题,如果我发现了什么,我会更新答案。我认为OptionParser#accept方法将发挥一定的作用,但是文档在解释accept方法的参数方面有些薄弱。 - Wand Maker

1
OptionParser不支持此功能;可以对其进行修补以实现此功能,但我不确定这是否值得麻烦。
考虑以下代码:
require 'optparse'

options = {}
OptionParser.new do |opt|
  opt.on('-m', '--move') { |o| options[:move] = o }
end.parse!

from_name, to_name = ARGV

puts "Should move: #{ options.key?(:move) }"
puts "From: #{ from_name }"
puts "To: #{ to_name }"

保存并运行具有各种参数组合的结果为:
> ruby test.rb --move from to
Should move: true
From: from
To: to

> ruby test.rb  from to
Should move: false
From:
To:

如果代码默认移动文件,则不需要使用--move标志,只需使用以下命令:
test.rb from to

考虑完全删除OptionParser块。

如果代码通常应该具有移动选项,则--move更为明智,可作为指示希望移动的标志。

ruby test.rb --move from to

我会编写代码来测试 options[:move],并在那时运行移动而不是复制的代码。
无论哪种情况,文件名都不应与标志绑定,它们应该分别提供,并且在 OptionParser 完成解析命令行并删除处理过的条目后从 ARGV 中检索。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接