gsub中的正则表达式,带有\ 1意外行为

时间:2014-02-11 13:31:28

标签: ruby regex string

此示例的行为符合预期:

"cl. 23".gsub(/([0-9]+)/, '|' + '\1'.to_s + '|')
# => "cl. |23|"

但这不是:

"cl. 23".gsub(/([0-9]+)/, '|' + '\1'.to_i.to_s + '|')
# => "cl. |0|"

为什么表达式'\1'.to_i.to_s会返回"0"

为了更加清晰,我的目标是能够使用\ 1:

在gsub中使用条件
 "cl. 23".gsub(/([0-9]+)/, '|' + ('\1'.to_i > 36 ? 'g' : 'service' ) + '|')

3 个答案:

答案 0 :(得分:2)

'\1'"\\1"\ + 1

这不是一个有效的数字表示。 (因为领先\); String#to_i会为此类字符串返回0

顺便说一句,如果您希望使用|包围该号码,则不需要to_ito_s。只需使用|\1|作为替换字符串。

"cl. 23".gsub(/([0-9]+)/, '|\1|')
# => "cl. |23|"

答案 1 :(得分:2)

在Ruby(或大多数其他编程语言)中,所有参数都在使用它们的方法调用之前进行评估。

在第一个例子中,首先评估参数,并变为:

gsub(/([0-9]+)/, '|' + '\1'.to_s + '|')
# => gsub(/([0-9]+)/, '|' + '\1' + '|')
# => gsub(/([0-9]+)/, '|\1|')

另一方面,在第二个例子中,参数被评估并变为:

gsub(/([0-9]+)/, '|' + '\1'.to_i.to_s + '|')
# => gsub(/([0-9]+)/, '|' + 0.to_s + '|')
# => gsub(/([0-9]+)/, '|' + '0' + '|')
# => gsub(/([0-9]+)/, '|0|')

同样,在使用它们的方法调用之前评估所有参数。由此可见,如果您希望替换字符串gsub依赖于匹配,则不能将替换公式放在参数中;你必须使用一个块。看起来这就是你想要的:

"cl. 23".gsub(/([0-9]+)/){'|' + ($1.to_i > 36 ? 'g' : 'service' ) + '|'}

哪个有效,但实际上并不聪明。更好的方法是

"cl. 23".gsub(/\d+/){|s| "|#{s.to_i > 36 ? "g" : "service"}|"}

答案 2 :(得分:1)

您似乎期望在regexp匹配的组上调用方法to_i。实际上它是在字符串'\1'上调用的。

String#to_i会返回0,因为documentation表示:

  

如果str的开头没有有效数字,则返回0。

irb> '\1'.to_i
# => 0