简体   繁体   English

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

[英]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_ito_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM