在OptionParser中,我可以强制选择一个选项,但如果我省略该值,则会将以下任何选项的名称作为值,从而搞砸了命令行解析的其余部分。 这是一个回应选项值的测试用例:
$ ./test_case.rb --input foo --output bar
output bar
input foo
现在省略第一个选项的值:
$ ./test_case.rb --input --output bar
input --output
有没有办法阻止它将另一个选项名称作为值? 谢谢!
以下是测试用例代码:
#!/usr/bin/env ruby
require 'optparse'
files = Hash.new
option_parser = OptionParser.new do |opts|
opts.on('-i', '--input FILENAME', 'Input filename - required') do |filename|
files[:input] = filename
end
opts.on('-o', '--output FILENAME', 'Output filename - required') do |filename|
files[:output] = filename
end
end
begin
option_parser.parse!(ARGV)
rescue OptionParser::ParseError
$stderr.print "Error: " + $! + "\n"
exit
end
files.keys.each do |key|
print "#{key} #{files[key]}\n"
end
答案 0 :(得分:9)
你想做的不是一个好主意。如果你真的有一个名为“--output”的文件怎么办?这是Unix上完全有效的文件名。每个Unix程序的选项解析都是按照ruby的方式进行的,所以你不应该改变它,因为那时你的程序将与其他任何东西任意不同,这是令人困惑的,并且违反了“最少惊喜的原则。”
真正的问题是:你为什么首先遇到这个问题?也许你正在从另一个程序运行你的程序,而父程序提供了一个空白文件名作为参数--input,这使得它看到--output作为参数--input。您可以通过始终引用在命令行上传递的文件名来解决此问题:
./test_case.rb --input "" --output "bar"
然后 - 输入将为空白,这很容易被发现。
另请注意,如果--input设置为--output(并且--output不是真实文件),您可以尝试打开--input文件。如果失败,请打印如下消息:
can't open input file: --output: file not found
这应该让用户明白他们做错了什么。
答案 1 :(得分:2)
在这种情况下,缺少必需的--output
选项,因此在调用parse!
后执行此操作:
unless files[:input] && files[:output]
$stderr.puts "Error: you must specify both --input and --output options."
exit 1
end
答案 2 :(得分:2)
试试这个:
opts.on('-i', '--input FILENAME', 'Input filename - required') do |filename|
files[:input] = filename
end
opts.on('-o', '--output FILENAME', 'Output filename - required') do |filename|
files[:output] = filename
end
opts.on("-h", "--help", "Show this message") do
puts opts
exit
end
begin
ARGV << "-h" if ARGV.size != 2
option_parser.parse!(ARGV)
rescue OptionParser::ParseError
$stderr.print "Error: " + $! + "\n"
exit
end
答案 3 :(得分:1)
好的 - 这个工作 - on()调用中的正则表达式允许任何字符串,只要它不以' - '开头
如果我没有将参数传递给--input并且下游有另一个选项,那么它将把该选项键作为--input的参数。 (例如--input --output)。正则表达式捕获,然后我检查错误消息。如果它报告的参数以' - '开头,则输出正确的错误消息,即缺少参数。不漂亮,但似乎有效。
这是我的工作测试用例:
#!/usr/bin/env ruby
require 'optparse'
files = Hash.new
option_parser = OptionParser.new do |opts|
opts.on('-i FILENAME', '--input FILENAME', /\A[^\-]+/, 'Input filename - required') do |filename|
files[:input] = filename
end
opts.on('-o FILENAME', '--output FILENAME', /\A[^\-]+/, 'Output filename - required') do |filename|
files[:output] = filename
end
end
begin
option_parser.parse!(ARGV)
rescue OptionParser::ParseError
if $!.to_s =~ /invalid\s+argument\:\s+(\-\-\S+)\s+\-/
$stderr.print "Error: missing argument: #{$1}\n"
else
$stderr.print "Error: " + $! + "\n"
end
exit
end
files.keys.each do |key|
print "#{key} #{files[key]}\n"
end