Ruby 如何从命令行传递哈希?
我有一个包含哈希的ruby脚本 例如:Ruby 如何从命令行传递哈希?,ruby,Ruby,我有一个包含哈希的ruby脚本 例如: animal_sound = { 'dog' => 'bark', 'cat' => 'meow' } myscript.rb --addsound snake:hiss 我想添加'snake'=>'hiss' 例如: myscript.rb --addsound "'snake' => 'hiss'" animal_sound.merge! 'snake' => 'hiss' => {"dog"=>"bark"
animal_sound = { 'dog' => 'bark', 'cat' => 'meow' }
myscript.rb --addsound snake:hiss
我想添加'snake'=>'hiss'
例如:
myscript.rb --addsound "'snake' => 'hiss'"
animal_sound.merge! 'snake' => 'hiss'
=> {"dog"=>"bark", "cat"=>"meow", "snake"=>"hiss"}
然后在我的脚本中,将其添加到animal_sound中
例如:
myscript.rb --addsound "'snake' => 'hiss'"
animal_sound.merge! 'snake' => 'hiss'
=> {"dog"=>"bark", "cat"=>"meow", "snake"=>"hiss"}
有办法做到这一点吗
以下是整个脚本:
#!/usr/bin/env ruby
require 'rubygems'
require 'micro-optparse'
options = Parser.new do |p|
p.option :addsound, "add sound"
end.process!
animal_sound = { 'dog' => 'bark', 'cat' => 'meow' }
if options[:add_sound]
newsound = options[:add_sound]
animal_sound.merge! newsound
end
puts animal_sound
当我运行脚本时,我得到:
$ bin/myscript.rb --addsound "'snake' => 'hiss'"
bin/myscript.rb:14:in `merge!': can't convert true into Hash (TypeError)
from bin/myscript.rb:14:in `<main>'
最终代码:
#!/usr/bin/env ruby
require 'rubygems'
require 'micro-optparse'
options = Parser.new do |p|
p.option :addsound, "add sound", default: ""
end.process!
animal_sound = { 'dog' => 'bark', 'cat' => 'meow' }
if options[:addsound]
animal, sound = options[:addsound].split(':')
animal_sound[animal] = sound
end
puts animal_sound
命令行:
$ bin/myscript.rb --addsound snake:hiss
{"dog"=>"bark", "cat"=>"meow", "snake"=>"hiss"}
我永远无法让合并工作。
每个帖子都很有帮助。谢谢 关于您的错误 注意这行
if options[:add_sound]
。如果为真,则基本上计算为。您得到错误是因为您正在将newsound
设置为true
,并试图将布尔值合并到哈希中。据我所知,.merge
的工作原理如下:hash1.merge(hash2)
传递命令行参数
与其传递参数“snake”=>“hiss”
,我建议将其设置为逗号分隔的列表,如下所示:“snake,hiss”
。从这里开始,在if options[:add_sound]
块中,可以使用逗号作为拆分器将字符串拆分为数组。最后,与使用.merge
不同,您可以像通常对Ruby中的任何哈希一样添加key:value<代码>动物声音[arr[0]]=arr[1]
请注意,此方法在使用单个键:值对时效果最佳。我相信您可以提交多个对,但您需要(通过此方法)通过一个附加字符(如/
可能)拆分成更多数组。p.option:addsound,“addsound”
^这使其成为一个标志(正确或错误)
您需要将其转换为一个开关,其值是下一个参数:
p.选项:添加声音,“添加声音”,默认值:
^这使它成为一个开关,字符串值将被分配给选项[:addsound]
newsound=options[:addsound]
^这里需要删除下划线并将字符串解析为哈希。
Eval是邪恶的。
例如,您可以在'=>'
上拆分它,然后忘记引用:
newsound = [ options[:addsound].split(' => ') ].to_h #and then merge it
(像这样传递参数--addsound snake:hiss,然后在':'
而不是'=>'
上拆分是另一个好选项。)
^在'=>'
上拆分应该会产生一个两成员数组。在这里,我将其放入另一个数组(两个成员数组的数组可转换为散列)以使其转换为散列
或者完全不合并和构建另一个哈希:
animal, sound = options[:addsound].split(' => ')
animal_sound[animal] = sound
最好将CLI接口与底层实现分离。事实上,将来您可能会决定将脚本从Ruby切换到另一种语言,并且您并不真正想要更改代码的调用方式 例如,我的建议是传递一个序列化的值
myscript.rb --addsound snake:hiss
在代码中,只需分解内容并将其合并
if options[:add_sound]
animal, sound = options[:add_sound].split(":")
animal_sound.merge!(animal => sound)
end
传递长的命令行参数通常是一个糟糕的计划。为什么不像其他许多实用程序那样,有一个参数来指定文件或从STDIN读取?YAML和JSON都非常易于阅读和编写,即使是手工操作,并且非常清晰地映射到原生Ruby结构。使用
YAML.load
或JSON.load
导入它们。感谢您的提示和帮助。我在你的代码中看到了逻辑,但我得到了以下错误:未定义的方法'split'for true:TrueClass(NoMethodError)
我在谷歌上搜索了一个答案,但没有找到我能理解和应用的答案。有什么见解吗?我看到onebree的回答告诉我,options[:addsound]
的评估结果是正确的。这就是问题所在。谢谢你的回复。与Simone Carletti的代码一样,我得到了以下错误:未定义的方法'split'for true:TrueClass(NoMethodError)
这就是为什么您应该选择我的响应:我对它进行了编辑,希望它更容易理解。阅读我答案的顶部,或为TL;DR:“您需要将默认值部分添加到p.option
行,将其从标志(布尔值)转换为开关(值是下一个参数)。好的……我使用您的animal,sound=options[:addsound].split('=>');animal_sound[animal]=声音
谢谢!事实上,我确实试着提高投票率。显然我还没有足够的“声望点数”。