我使用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上看不到太多文档。我甚至试过微解析,但它要求默认值,而不是我的选择:(
答案 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!
没有经过测试,但是我们一直在做类似的工作,所以将它保存到一个文件中并用棍子捅一会儿,看看你想出了什么。