[英]regular expression in gsub with \1 unexpected behaviour
This example behaves as expected: 此示例的行为符合预期:
"cl. 23".gsub(/([0-9]+)/, '|' + '\1'.to_s + '|')
# => "cl. |23|"
but this doesn't: 但这不是:
"cl. 23".gsub(/([0-9]+)/, '|' + '\1'.to_i.to_s + '|')
# => "cl. |0|"
Why does the expression '\\1'.to_i.to_s
return "0"
? 为什么表达式
'\\1'.to_i.to_s
返回"0"
?
for more clarity, my aim is to be able to use a condition in gsub using \\1: 为了更加清晰,我的目标是能够使用\\ 1在gsub中使用条件:
"cl. 23".gsub(/([0-9]+)/, '|' + ('\1'.to_i > 36 ? 'g' : 'service' ) + '|')
'\\1'
is "\\\\1"
: \\
+ 1
. '\\1'
是"\\\\1"
: \\
+ 1
。
It is not a valid numerical representation. 这不是有效的数字表示形式。 (because of leading
\\
); (由于领先
\\
); String#to_i
returns 0
for such string. String#to_i
对该字符串返回0
。
BTW, if you want surround the number with |
顺便说一句,如果您想用
|
括住数字 , you don't need to_i
, to_s
. ,您不需要
to_i
和to_s
。 Just use |\\1|
只需使用
|\\1|
as replacement string. 作为替换字符串。
"cl. 23".gsub(/([0-9]+)/, '|\1|')
# => "cl. |23|"
In Ruby (or in most other programming languages), all arguments are evaluated before the method call that uses them. 在Ruby(或大多数其他编程语言)中,所有参数都在使用它们的方法调用之前进行求值。
With the first example, the arguments are first evaluated, and becomes: 在第一个示例中,参数首先被求值,并变为:
gsub(/([0-9]+)/, '|' + '\1'.to_s + '|')
# => gsub(/([0-9]+)/, '|' + '\1' + '|')
# => gsub(/([0-9]+)/, '|\1|')
On the other hand, with the second example, the arguments are evaluated and becomes: 另一方面,在第二个示例中,参数被求值并变为:
gsub(/([0-9]+)/, '|' + '\1'.to_i.to_s + '|')
# => gsub(/([0-9]+)/, '|' + 0.to_s + '|')
# => gsub(/([0-9]+)/, '|' + '0' + '|')
# => gsub(/([0-9]+)/, '|0|')
Again, all arguments are evaluated before the method call that uses them . 同样, 所有参数都在使用它们的方法调用之前进行评估 。 From this, it follows that, if you want the replacement string of
gsub
to depend on the match, you cannot put the replacement formula in the argument; gsub
,如果要让gsub
的替换字符串取决于匹配项,则不能将替换公式放在参数中。 you have to use a block. 您必须使用一个块。 Looks like this is what you wanted:
看起来这是您想要的:
"cl. 23".gsub(/([0-9]+)/){'|' + ($1.to_i > 36 ? 'g' : 'service' ) + '|'}
which works but actually is not smart. 可行,但实际上并不明智。 A better way is
更好的方法是
"cl. 23".gsub(/\d+/){|s| "|#{s.to_i > 36 ? "g" : "service"}|"}
It seems you are expecting the method to_i
to be called on the group matched by the regexp. 似乎您希望在
to_i
则表达式匹配的组上调用to_i
方法。 Actually it is called on the string '\\1'
. 实际上,它是在字符串
'\\1'
上调用'\\1'
。
String#to_i
returns 0
because, as the documentation says: String#to_i
返回0
原因是,如文档所述 :
If there is not a valid number at the start of str, 0 is returned.
如果在str的开头没有有效数字,则返回0。
irb> '\1'.to_i
# => 0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.