String#gsub!
имеет две формы, одну из которых вы передаете в виде строки в качестве второго аргумента, в которой ссылки на переменные, такие как $1
и $2
, заменяются соответствующим соответствием подвыражения, а другая - в которой вы передаете блок, который вызывается с аргументами, для которых передаются совпадения подвыражения. Вы используете блочную форму при вызове gsub!
, но строка в вашем хэше пытается использовать форму, в которой передается строка.
Кроме того, переменная интерполяция в вашей строке происходит до совпадения; интерполяция переменных происходит, как только строка оценивается, то есть во время создания вашего хэша, в то время как для этого вам понадобится интерполяция переменных, которая произойдет после замены подвыражения (что никогда не происходит; интерполяция переменных произойдет сначала, и результирующая строка будет передана в gsub!
для gsub!
, чтобы заменить совпадение подвыражения для $1
, но $1
уже был бы оценен и больше не был в строке, так как интерполяция уже произошла ).
Теперь, как это исправить? Что ж, вы, вероятно, захотите сохранить свои блоки непосредственно в хэше (чтобы строки не интерпретировались при создании хэша, а вместо этого, когда gsub!
вызывает блок), с аргументом, соответствующим совпадению, и $1
, $2
и т. Д. Связаны с соответствующими совпадениями подвыражения. Чтобы превратить блок в значение, которое может быть сохранено и впоследствии извлечено, вам необходимо добавить к нему lambda
; затем вы можете снова передать его как блок, добавив префикс &
:
hash = {
/(\d+) years/ => lambda { "#{$1.to_f*2} days" },
/cannot/ => lambda { 'of course we CAN' }
}
hash.each {|k,v|
a.gsub!(k, &v)
}