我想要一个包含位置参数标记(未命名)的字符串,为它提供值的数组(而不是哈希),并对其求值。
用例作为示例将有点像ARGV。
例如,
# given:
string = "echo $1 ; echo $@"
values = ["hello", "world"]
# expected result:
"echo hello ; echo hello world"
以下功能是我能想到的最好的功能:
def evaluate_args(string, arguments)
return string unless arguments.is_a? Array and !arguments.empty?
# Create a variable that can replace $@ with all arguments, and quote
# arguments that had "more than one word" originally
all_arguments = arguments.map{|a| a =~ /\s/ ? "\"#{a}\"" : a}.join ' '
# Replace all $1 - $9 with their respective argument ($1 ==> arguments[0])
string.gsub!(/\$(\d)/) { arguments[$1.to_i - 1] }
# Replace $@ or $* with all arguments
string.gsub!(/\$[*|@]/, all_arguments)
return string
end
在我看来,它可以而且应该更简单。
我希望找到更接近Kernel.sprintf
做事方法的东西-例如"string with %{marker}" % {marker: 'value'}
因此,尽管这个问题几乎已经为我解决了(我认为),但我还是想知道我是否错过了可以使它更加优雅的东西。
似乎您正在尝试重现Bash风格的变量扩展,这是一个非常复杂的问题。不过,至少可以用两种方法简化代码:
Kernel.sprintf
的内置位置参数功能。下面的代码通过$1
用sprintf
等价的代替%1$s
。require 'shellwords'
def evaluate_args(string, arguments)
return string unless arguments.is_a? Array and !arguments.empty?
tmpl = string.gsub(/\$(\d+)/, '%\1$s')
(tmpl % arguments).gsub(/\$[*@]/, arguments.shelljoin)
end
string = "echo $1 ; echo $@"
values = ["hello", "world"]
puts evaluate_args(string, values)
# => echo hello ; echo hello world
如果您没有$*
要求,建议您删除类Bash格式并使用sprintf
,因为它涵盖了您提到的所有其他内容。即使这样,您也可以通过sprintf
对其他所有内容使用格式来进一步简化事情:
def evaluate_args(string, arguments)
return string unless arguments.is_a? Array and !arguments.empty?
string.gsub('%@', arguments.shelljoin) % arguments
end
string = "echo %1$s ; echo %@"
values = ["hello", "world"]
puts evaluate_args(string, values)
# => echo hello ; echo hello world
如果要%{1}
与之一起使用,则sprintf
可以将输入数组转换为哈希,其中将整数索引转换为符号键,例如["hello", "world"]
变为{ :"1" => "hello", :"2" => "world" }
:
require "shellwords"
def evaluate_args(string, arguments)
return string unless arguments.is_a? Array and !arguments.empty?
string % {
:* => arguments.shelljoin,
**arguments.map.with_index {|val,idx| [ :"#{idx + 1}", val ] }.to_h
}
end
string = "echo %{1} ; echo %{*}"
values = ["hello", "world"]
puts evaluate_args(string, values)
# => echo hello ; echo hello world
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句