0

如果我运行此代码:

"Retailer Staff $5.60".gsub(/.*\$(\d+(\.\d+)?).*/, $1)
# => 5.60

然后我将值更改为:

"Retailer Staff $5".gsub(/.*\$(\d+(\.\d+)?).*/, $1)
# => 5.60

答案停留在5.60。然后,如果我再次运行同一行,我得到:

"Retailer Staff $5".gsub(/.*\$(\d+(\.\d+)?).*/, $1)
# => 5

发生了什么?为什么相同的代码运行两次会给出两个答案?gsub缓存东西吗?

4

2 回答 2

2

您的代码没有真正的意义,也没有按照您的想法执行。

$1是一个全局变量,因此第一个变量将用您调用之前gsub的任何内容替换匹配的模式。这个:$1 gsub

"Retailer Staff $5.60".gsub(/.*\$(\d+(\.\d+)?).*/, $1)

相当于:

confusion = $1
"Retailer Staff $5.60".gsub(/.*\$(\d+(\.\d+)?).*/, confusion)

当你真的想说:

"Retailer Staff $5.60".gsub(/.*\$(\d+(\.\d+)?).*/) { $1 }

这样gsub可以$1在屈服于块之前设置。

一旦您了解了何时$1设置以及何时评估它,那么其他一切都会到位。您的第一个电话gsub最终设置$1'5.60',然后您的下一个电话只是一种过于复杂的说法:

"Retailer Staff $5".gsub(/.*\$(\d+(\.\d+)?).*/, '5.60')

它设置$1'5'。等等。

于 2017-10-10T02:27:12.267 回答
2

我相信这种情况正在发生,因为$1实际上是对在最后一个处理的正则表达式中找到的第一个捕获组的全局引用:ruby 2.4 docs。因此,在您的情况下,您可能已经测试了正则表达式并在“5.60”上匹配。这是我在 ruby​​ 2.0 中运行的带注释的片段:

# Since no regex has executed yet $1 is nil
irb(main):001:0> "Retailer Staff $5.60".gsub(/.*\$(\d+(\.\d+)?).*/, $1)
TypeError: no implicit conversion of nil into String
    from (irb):1:in 'gsub'
    from (irb):1
    from /usr/bin/irb:12:in '<main>'
irb(main):002:0> "Retailer Staff $5.60".gsub(/.*\$(\d+(\.\d+)?).*/, 'some value')
=> "some value"
irb(main):003:0> $1   # Now we have executed a regex so $1 is set
=> "5.60"             
irb(main):004:0> "Retailer Staff $5.60".gsub(/.*\$(\d+(\.\d+)?).*/, $1) 
=> "5.60"
irb(main):005:0> $1   # This is still the same value because we matched the same string
=> "5.60"             
irb(main):006:0> "Retailer Staff $5".gsub(/.*\$(\d+(\.\d+)?).*/, $1)
=> "5.60"
irb(main):007:0> $1   # Now we have matched the 5 so $1 has the new value
=> "5"                
irb(main):008:0> "Retailer Staff $5".gsub(/.*\$(\d+(\.\d+)?).*/, $1)
=> "5"
irb(main):009:0> $1
=> "5"
于 2017-10-10T02:28:30.193 回答