16

在 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
4

4 回答 4

8

你想做的不是一个好主意。如果你真的有一个名为“--output”的文件怎么办?这是 Unix 上完全有效的文件名。每个 Unix 程序的选项解析都按照 ruby​​ 的方式进行,所以你不应该改变它,因为那样你的程序将与其他程序任意不同,这是令人困惑的并且违反了“最小意外原则”。

真正的问题是:为什么你首先会遇到这个问题?也许您正在从另一个程序运行您的程序,并且父程序提供了一个空白文件名作为 --input 的参数,这使得它看到 --output 作为 --input 的参数。您可以通过始终引用您在命令行上传递的文件名来解决此问题:

./test_case.rb --input "" --output "bar"

然后 --input 将是空白的,这很容易检测到。

另请注意,如果 --input 设置为 --output (并且 --output 不是真实文件),您可以尝试打开 --input 文件。如果失败,打印如下消息:

can't open input file: --output: file not found

这应该让用户清楚他们做错了什么。

于 2010-03-31T15:47:19.500 回答
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
于 2012-02-01T11:27:56.027 回答
1

在这种情况下,--output缺少强制选项,因此请在调用后执行此操作parse!

unless files[:input] && files[:output]
  $stderr.puts "Error: you must specify both --input and --output options."
  exit 1
end
于 2010-03-30T20:00:09.040 回答
0

好的 - 这有效 - on() 调用中的正则表达式允许任何字符串,只要它不以“-”开头

如果我没有将参数传递给--input,并且下游还有另一个选项,那么它将将该选项键作为--input 的参数。(例如——输入——输出)。正则表达式捕获了它,然后我检查了错误消息。如果它报告的参数以“-”开头,我会输出正确的错误消息,即缺少参数。不漂亮,但它似乎工作。

这是我的工作测试用例:

#!/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
于 2010-03-30T21:11:15.767 回答