在Ruby中评估表达式

时间:2013-12-09 19:39:16

标签: ruby string gsub

此代码全部有效并生成11 22和2032。

date = '11-22-2032'
mon, day, year = $1, $2, $3 if date =~ /(\d\d)-(\d\d)-(\d\d)/
p mon,day,year

但是这样的事情不起作用:

str = "This is a string"
str.gsub!(/(\w+)/, "1#{$1}")
p str => prints all whitespace

Ruby是否从右侧开始计算表达式(因此第一个示例的工作原理是什么?)如何使第二个示例工作(在同一个.gsub方法中使()包含在()中,所以我每个单词之前可以加1吗?

3 个答案:

答案 0 :(得分:2)

您的第二个示例不起作用的事实与if的评估顺序无关。

相反,请使用\1\2作为插值变量。

str = "This is a string"
str.gsub!(/(\w+)/, '1\1')
print str

另请注意,"\1"已进行插值,您需要'\1'

答案 1 :(得分:1)

我不认为gsub以可替换字符串中使用的方式设置全局变量$1$2等(请参阅http://www.ruby-doc.org/core-1.9.3/String.html#method-i-gsub) 。相反,请使用反向引用\1(因为您将它们包含在双引号字符串中,您需要双重转义为"\\1"):

>> str = "This is a string"
=> "This is a string"
>> str.gsub!(/(\w+)/, "1\\1")
=> "1This 1is 1a 1string"

答案 2 :(得分:0)

之所以不能使用$1是因为您要将字符串作为arg传递给gsub方法,这意味着它与内插的$1一起使用,在之前 gsub被设置并使用。 @berkes的答案是避免这种情况并获得匹配的组的一种方法,可能是最好的方法。

但是仅供参考,您也可以使用一个块:

str = "This is a string"
str.gsub!(/(\w+)/) {"1#{$1}"}

因为只有在调用gsub之后才进行匹配,才对块进行求值。