OptionParser用于解析参数表单文件而不是命令行

时间:2013-04-24 21:12:30

标签: ruby arguments optparse optionparser

我使用Ruby来执行一个带有命令行参数的代码。 现在我尝试使用不同选项的相同程序,所以我将选项放在一个文件中,我希望程序读取每行解释选项并相应地执行程序。

但是我收到了这个错误。 “C:/Ruby193/lib/ruby/1.9.1/optparse.rb:1348:在block in parse_in_order': undefined method shift'中为”--c execue --query unix --Servername abc123“:String(NoMethodError)”< / p>

我理解它正在读取文件并将该行视为字符串。但是想知道是否有办法克服这种转换错误并将该行视为在命令提示符下输入。或任何更好的解决方案。

这是我的代码。

require 'optparse'
require 'micro-optparse'
# --command execue --query unix command --Servername abc123
f =File.open("list_of_commands.txt", "r")
f.each_line { |line| 
line= line.chomp
#line = "--c execue --query unix --Servername abc123"
#line = eval("\"#{line}\"")
puts line

 options = {}
OptionParser.new do |opts|

  opts.on("-c", "--command result,execue,chart,scpfile", String, "Single command to execute ") do |c|
    options[:comd] = c
  end

  opts.on("-q", "--query remote command, unix command", String, "performs the command on local or remote machine") do |q|
    options[:query] = q
  end

  opts.on("-s", "--servername CHSXEDWDC002 ", String, "server name to execute the command") do |v|
    options[:hname] = v
  end

    opts.on_tail('-h', '--help', 'Show this message') do
    puts opts
     exit
   end

 end.parse!(line)
 p options
 }

该文件的内容如下 --c execue --query unix --Servername abc123

我也尝试使用micro-optparse但遇到同样的错误。任何解决方法?

更新 根据“@mu太短”的建议,我尝试了下面的选项。 end.parse!(“#{Shellwords.shellsplit(line)}”)和/或 end.parse!(Shellwords.shellsplit(线))。 但他们都没有工作。

我还尝试使用“line = line.split(”\ t“)”然后将行拆分为数组 end.parse!(线)。出来的 --c execue --query unix --Servername abc123

但现在我收到错误作为阻止:无效选项--c执行

更新:#2 看错误,问题是错误的参数(-c。但感谢用户“@ mu太短”,建议使用Array。

更新:3 传递数组只适用于-c这样的参数的简短形式,但是当提供长格式时,它失败并带有无效的参数erorr。

我在optparse上看不到太多文档。我甚至试过微解析,但它要求默认值,而不是我的选择:(

2 个答案:

答案 0 :(得分:2)

parse!方法需要数组作为参数,而不是字符串。您可能希望使用Shellwords.shellsplit而非String#split(或类似的手动方法)将line转换为数组,以防您必须处理引用等等。像这样:

OptionParser.new do |opts|
  #...
end.parse!(Shellwords.shellsplit(line))

答案 1 :(得分:2)

虽然您可以将命令行参数放入文件,标记和所有内容,但有更好的方法可以记住配置设置。

使用YAML文件,而不是存储标志。 YAML是一种出色的数据格式,可以轻松转换为Ruby哈希和对象。 “Yaml Cookbook”是一个非常有用的页面,可以用Ruby学习格式的来龙去脉。有无数其他语言的YAML解析器,可以轻松共享设置,这在系统增长时非常有用。

使用一些创意代码,您可以使用YAML作为基本设置,并让CLI标志覆盖存储的设置。

如果您不熟悉YAML,可以使用以下内容轻松启动文件:

require 'yaml'

data = {
  'command' => %w[result execute chart scpfile],
  'query' => ['remote command', 'unix command'],
  'servername' => 'CHSXEDWHDC002',
}

puts data.to_yaml

哪个输出:

---
command:
- result
- execute
- chart
- scpfile
query:
- remote command
- unix command
servername: CHSXEDWHDC002

将该输出重定向到以.yaml结尾的文件,然后您就可以了。

要将其读回脚本,请使用:

require 'yaml'

data = YAML.load_file('path/to/data.yaml')

快速往返测试显示:

require 'yaml'

data = {
  'command' => %w[result execute chart scpfile],
  'query' => ['remote command', 'unix command'],
  'servername' => 'CHSXEDWHDC002',
}

YAML.load(data.to_yaml)

看起来像:

{"command"=>["result", "execute", "chart", "scpfile"],
"query"=>["remote command", "unix command"],
"servername"=>"CHSXEDWHDC002"}

如果您想要存储在YAML文件中的默认值,并使用命令行标志覆盖它们,请从文件中读取数据,然后使用该结果对象作为OptionParse的基础:

require 'optparse'
require 'yaml'

# Note, YAML can deal with symbols as keys, but other languages might not like them.
options = {
  :comd => %w[result execute chart scpfile],
  :query => ['remote command', 'unix command'],
  :hname => 'CHSXEDWHDC002',
}

# we'll overwrite the options variable to pretend we loaded it from a file.
options = YAML.load(options.to_yaml)

OptionParser.new do |opts|

  opts.on("-c", "--Command result,execue,chart,scpfile", String, "Single command to execute ") do |c|
    options[:comd] = c
  end

  opts.on("-q", "--query remote command, unix command", String, "performs the command on local or remote machine") do |q|
    options[:query] = q
  end

  opts.on("-s", "--Servername CHSXEDWHDC002 ", String, "server name to execute the command") do |v|
    options[:hname] = v
  end

  opts.on_tail('-h', '--help', 'Show this message') do
    puts opts
    exit
  end

end.parse!

没有经过测试,但是我们一直在做类似的工作,所以将它保存到一个文件中并用棍子捅一会儿,看看你想出了什么。