具有异常处理的Ruby optparse奇数行为

具有异常处理的Ruby optparse奇数行为,ruby,arguments,command-line-interface,optionparser,Ruby,Arguments,Command Line Interface,Optionparser,我正致力于通过对该工具的CLI组件进行错误处理,使CLI ruby工具更加健壮。我正在使用optpasse,文档显示标志可以有强制参数和可选参数。我只是看到一些奇怪/恼人的行为 对于一种情况,标志的参数是强制性的(使用等号),我试图让它失败,但它仍然有效,它只是抓住了下一个标志('-u')作为该标志的参数,这会导致其余的解析以一种不太理想的方式进行。我想这是可以的,因为“-…”可能有效,但因为我使用等号设置开关的值,所以我假设“空格”样式的赋值不起作用 op = OptionParser.new

我正致力于通过对该工具的CLI组件进行错误处理,使CLI ruby工具更加健壮。我正在使用optpasse,文档显示标志可以有强制参数和可选参数。我只是看到一些奇怪/恼人的行为

对于一种情况,标志的参数是强制性的(使用等号),我试图让它失败,但它仍然有效,它只是抓住了下一个标志('-u')作为该标志的参数,这会导致其余的解析以一种不太理想的方式进行。我想这是可以的,因为“-…”可能有效,但因为我使用等号设置开关的值,所以我假设“空格”样式的赋值不起作用

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
myprog -d mydb -u positionalarg
然后,options[:user]是nil(ok),options[:db]是mydb,剩下一个位置参数

通过此解析:

myprog -u myuser -d mydb positionalarg
然后options[:user]为nil(不正常),options[:db]为mydb,剩下两个位置参数:myuser和positionarg(不正常)。我的错误检查再次显示位置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 -u -d mydb positionalarg
myprog -d mydb -u positionalarg
然后,options[:db]是mydb(ok),options[:user]是positionalg,并且没有剩余的位置参数。请注意,-d mydb可以使用空格,即使是我用等号指定的空格

似乎很多人都是通过optparse.parse来实现ruby CLIs的!并将ARGV中的其余条目作为位置参数,但我认为在将ARGV传递给optpasse之前,最好先从远端去掉位置参数(除非在位置参数数量可变的情况下失败)

我相信我可以围绕所有这些进行编程,但如果在OptPass中有我不知道的方法,我宁愿不这样做


也许最好的办法是避免使用带有可选参数的标志:),但任何建议都将不胜感激。

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

如果我将此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,为Linux删除
@echo off
):

我得到:

=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长格式标志的惯用方法,而短格式通常不使用等号。