如何处理 Ruby OptionParser 中缺少的强制参数?
在 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
In OptionParser I can make an option mandatory, but if I leave out that value it will take the name of any following option as the value, screwing up the rest of the command line parsing.
Here is a test case that echoes the values of the options:
$ ./test_case.rb --input foo --output bar
output bar
input foo
Now leave out the value for the first option:
$ ./test_case.rb --input --output bar
input --output
Is there some way to prevent it taking another option name as a value?
Thanks!
Here is the test case code:
#!/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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你想做的事情并不是一个好主意。如果你确实有一个名为“--output”的文件怎么办?这是 Unix 上完全有效的文件名。每个 Unix 程序的选项解析的工作方式都与 ruby 程序的工作方式相同,因此您不应该更改它,因为这样您的程序将与其他程序任意不同,这会令人困惑并违反“最少意外原则”。
真正的问题是:你为什么会遇到这个问题?也许您正在从另一个程序运行您的程序,并且父程序提供一个空白文件名作为 --input 的参数,这使其将 --output 视为 --input 的参数。您可以通过始终引用在命令行上传递的文件名来解决此问题:
然后 --input 将为空,这很容易检测到。
另请注意,如果 --input 设置为 --output (并且 --output 不是真实文件),您可以尝试打开 --input 文件。如果失败,请打印一条消息,例如:
这应该让用户清楚他们做错了什么。
What you want to do is not a good idea. What if you really have a file named "--output"? This is a perfectly valid filename on Unix. Every Unix program's option parsing works the way the ruby one is doing, so you shouldn't change it, because then your program will be arbitrarily different from everything else, which is confusing and violates the "principle of least surprise."
The real question is: why are you having this problem in the first place? Perhaps you're running your program from another program, and the parent program is providing a blank filename as the parameter to --input, which makes it see --output as the parameter to --input. You can work around this by always quoting the filenames you pass on the command line:
Then --input will be blank, and that's easy to detect.
Also note that if --input is set to --output (and --output is not a real file) you can just try to open the --input file. If it fails, print a message like:
And that should make it clear to the user what they did wrong.
试试这个:
try this:
在这种情况下,缺少强制的
--output
选项,因此请在调用parse!
后执行此操作:In this case, the mandatory
--output
option is missing, so do this after callingparse!
:好的 - 这有效 - on() 调用中的正则表达式允许任何字符串,只要它不以 '-' 开头
如果我不将参数传递给 --input 并且下游还有另一个选项,那么它会将该选项键作为 --input 的参数。 (例如--输入--输出)。正则表达式捕获该错误,然后我检查错误消息。如果它报告的参数以“-”开头,我会输出正确的错误消息,即缺少参数。不漂亮,但似乎有效。
这是我的工作测试用例:
OK - this works - the regular expression in the on() call allows any string as long as it doesn't start with a '-'
If I don't pass an argument to --input and there is another option downstream then it will take that option key as the argument to --input. (e.g. --input --output). The regexp catches that and then I check the error message. If the argument it reports starts with '-' I output the correct error message, namely that there is a missing argument. Not pretty but it seems to work.
Here is my working test case: