【问题标题】:Ruby optparse odd behavior with exception handlingRuby optparse 异常处理的奇怪行为
【发布时间】:2014-01-21 20:25:06
【问题描述】:

我正在努力通过工具的 CLI 组件的错误处理来使 CLI ruby​​ 工具更加健壮。我正在使用 optparse 并且文档显示标志可以具有强制和可选参数。我只是看到一些奇怪/烦人的行为。

对于标志的参数是强制性的(使用等号)的一种情况,我试图让它失败但它仍然有效,它只是抓住了下一个标志('-u')作为那个参数而是标记,这会导致其余的解析以不太理想的方式出现。我想这还不错,因为'-....' 可能是有效的,但是因为我使用等号来设置开关的值,所以我假设'space' 样式分配不起作用.

op = OptionParser.new do |x|
  x.on("-u", "--user=USER", "user flag") do |user|  options[:user] = user end
  x.on("-d", "--db=DATABASE", "database flag") do |db|  options[:db] = db end
end

如果我通过以下 CLI 输入:

myprog -u -d mydb positionalarg

然后在解析过程中,它将 options[:user] 设置为 -d,并且 options[:db] 为 nil,因为它没有遇到并且有 2 个位置参数而不是 1 个。显然这是一个用户错误,但我想要捕获它并显示一个真正的错误,而不仅仅是返回一个错误(在工具的情况下),应该从以下列表中只传递一个位置参数:......真正的问题是缺少 -u 标志这是必需的参数,因此鉴于 optparse 有一个 ArgumentMissing 异常,我认为这就是 .parse!会扔。

但是,对于带有可选参数(使用等号)的标志,如果你这样做,它实际上是可选的:-a -b=something,但这不起作用:-a something -b=somethingelse。强制该值的唯一方法是使用等号:-a=something -b=somethingelse。鉴于先前带有等号的强制性参数的行为,我认为不会是这种情况。示例:

op = OptionParser.new do |x|
  x.on("-u", "--user[=USER]", "user flag") do |user|  options[:user] = user unless user.nil? end
  x.on("-d", "--db=DATABASE", "database flag") do |db|  options[:db] = db end
end

所以解析:

myprog -u -d mydb positionalarg

那么 options[:user] 是 nil (ok) 并且 options[:db] 是 mydb 并且剩下一个位置参数。

通过这个解析:

myprog -u myuser -d mydb positionalarg

然后 options[:user] 为 nil(不正常), options[:db] 为 mydb 并且剩下两个位置参数:myuser 和 positionalarg(不正常)。我的错误检查再次与位置 arg 计数有关。似乎如果使用强制标志参数,如果空格和 = 都有效,那么对于可选标志参数,它应该是相同的,但事实并非如此。

另一个问题是带有可选参数(使用空格)的标志很好,除非它们位于命令的末尾,然后将位置参数作为标志参数。

例子:

op = OptionParser.new do |x|
  x.on("-u", "--user [USER]", "user flag") do |user|  options[:user] = user unless user.nil? end
  x.on("-d", "--db=DATABASE", "database flag") do |db|  options[:db] = db end
end

所以解析:

myprog -d mydb -u positionalarg

那么 options[:db] 是 mydb (ok) 并且 options[:user] 是 positionalarg 并且没有剩余的位置参数。请注意, -d mydb 可以使用空格,即使是我用等号指定的空格。

似乎很多人通过执行 optparse .parse 来执行 ruby​​ CLI!并将 ARGV 中的剩余条目作为位置参数,但我认为在将 ARGV 传递给 optparse 之前先将位置参数从远端剥离可能会更好(除非在位置参数数量可变的情况下失败。

我相信我可以围绕所有这些进行编程,但如果我不知道在 optparse 中有方法可以做到这一点,我不希望这样做。

也许最好的办法是避免带有可选参数的标志:),但任何建议都会受到赞赏。

【问题讨论】:

  • 你为什么不向我们展示你在做什么而不是试图描述它?源代码,像一张图,值一千字。事实上,这不是一个可用的问题:“有关您编写的代码问题的问题必须在问题本身中描述具体问题 - 并包括有效的代码来重现它。有关指导,请参阅SSCCE.org。”跨度>

标签: ruby arguments command-line-interface optionparser


【解决方案1】:

为什么在选项的定义中使用=documentation 中的示例不要使用它们。

如果我将此 MWE 定义为test.rb

require 'optparse'

puts "\n=Call with #{ARGV.inspect}"
options = {}

op = OptionParser.new do |x|
  x.on("-u", "--user [USER]", "user flag") do |user|  options[:user] = user unless user.nil? end
  x.on("-d", "--db DATABASE", "database flag") do |db|  options[:db] = db end
end

op.parse!

puts "Options: #{options.inspect}"
puts "ARGV     #{ARGV.inspect}"

并使用此 batfile 调用它(Windows,删除 @echo off for Linux):

@echo off
test.rb -h
test.rb -u -d mydb positionalarg
test.rb -u myuser -d mydb positionalarg
test.rb --user=myuser -d mydb positionalarg

我明白了:

=Call with ["-h"]
Usage: test [options]
    -u, --user [USER]                user flag
    -d, --db DATABASE                database flag

=Call with ["-u", "-d", "mydb", "positionalarg"]
Options: {:db=>"mydb"}
ARGV     ["positionalarg"]

=Call with ["-u", "myuser", "-d", "mydb", "positionalarg"]
Options: {:user=>"myuser", :db=>"mydb"}
ARGV     ["positionalarg"]

=Call with ["--user=myuser", "-d", "mydb", "positionalarg"]
Options: {:user=>"myuser", :db=>"mydb"}
ARGV     ["positionalarg"]

【讨论】:

  • 在长格式标志中使用等号是执行 CLI 长格式标志的惯用方式,而短格式通常不使用等号。
猜你喜欢
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多