使用反向引用和哈希时的Ruby gsub问题 [英] Ruby gsub problem when using backreference and hashes

查看:107
本文介绍了使用反向引用和哈希时的Ruby gsub问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码使用正则表达式(键)和替换(值)定义散列。然后它遍历散列并相应地替换字符串。

简单的字符串替换效果很好,但是当我需要在代替它之前计算resut(几年到几天的变化),它不会。关键是预先定义哈希。



我错过了什么?任何帮助将非常感激。

  a =45年后我们无法使用这个东西。 

hash = {
/(\d +)years / => #{$ 1.to_f * 2}+'days',
/ can not / => '当然,我们可以'
}

hash.each {| k,v |

a.gsub!(k){v}
}

存放

谢谢!

解决方案

String#gsub!有两种形式,一种是在字符串中传入第二个参数,其中像 $ 1 $ 2这样的变量引用被替换为相应的子表达式匹配,并且您在其中传入一个块,该块通过传入子表达式匹配的参数调用。在调用<$ c $时使用块形式c> gsub!,但是你的散列中的字符串试图使用传入字符串的表单。



另外,字符串中的变量插值发生在之前匹配;变量插值在字符串被计算后立即发生,这就是在构建哈希时,为此,您需要在发生子表达替换后发生变化插值(这绝不是这种情况;变量插值将会发生首先,结果字符串将被传递给 gsub!用于 gsub!来替代子表达式匹配 $ 1 ,但是 $ 1 已经被计算过,不再在字符串中,因为插值已经发生) p>

现在,如何解决这个问题?那么,你可能希望直接将块存储在散列中(以便在构造散列时不会解释这些字符串,但是当 gsub!调用块时) ,与参数对应的匹配,以及 $ 1 $ 2 等绑定到适当的子表达式匹配。为了将块转换为可以存储并随后检索的值,需要向其中添加 lambda ;那么你可以通过以& 为前缀将它作为块重新传递:

  hash = {
/(\d +)years / => lambda {#{$ 1.to_f * 2} days},
/ can not / => lambda {'当然我们可以'}
}

hash.each {| k,v |
a.gsub!(k,& v)
}


The following code defines a hash with regular expressions (keys) and replacements (values). Then it iterates over the hash and replaces the string accordingly.

Simple string substitution works well, but when I need to compute the resut before substituting it (the case of years to days change), it does not. And it is key that the hash is defined beforehand.

What am I missing? Any help will be very appreciated.

a = "After 45 years we cannot use this thing."

hash = {
  /(\d+) years/ => "#{$1.to_f*2}" + ' days',
  /cannot/      => 'of course we CAN'  
}

hash.each {|k,v| 

  a.gsub!(k) { v }
}

puts a

Thanks!

解决方案

String#gsub! has two forms, one in which you pass in a string as the second argument, in which variable references like $1 and $2 are replaced by the corresponding subexpression match, and one in which you pass in a block, which is called with arguments which have the subexpression matches passed in. You are using the block form when calling gsub!, but the string in your hash is attempting to use the form in which a string is passed in.

Furthermore, the variable interpolation in your string is occurring before the match; variable interpolation happens as soon as the string is evaluated, which is at the time your hash is being constructed, while for this to work you would need variable interpolation to happen after the subexpression replacement happens (which is never the case; variable interpolation will happen first, and the resulting string would be passed in to gsub! for gsub! to substitute the subexpression match for $1, but $1 would have already been evaluated and no longer in the string, as the interpolation has already occurred).

Now, how to fix this? Well, you probably want to store your blocks directly in the hash (so that the strings won't be interpreted while constructing the hash, but instead when gsub! invokes the block), with an argument corresponding to the match, and $1, $2, etc. bound to the appropriate subexpression matches. In order to turn a block into a value that can be stored and later retrieved, you need to add lambda to it; then you can pass it in as a block again by prefixing it with &:

hash = {
  /(\d+) years/ => lambda { "#{$1.to_f*2} days" },
  /cannot/      => lambda { 'of course we CAN' }
}

hash.each {|k,v|
  a.gsub!(k, &v)
}

这篇关于使用反向引用和哈希时的Ruby gsub问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆