我在gsub!
的replace参数中使用lambda。当lambda以不同的方法定义时,Regexp.last_match
或$~
为空,违反lambda在调用时评估表达式的预期行为。如果我运行此代码,我将收到错误,但如果我取消注释转录中的第一行,它将起作用。
class Test
def initialize
@@replace = lambda { "#{callback('*', Regexp.last_match)}" }
end
def transcribe(s)
#@@replace = lambda { "#{callback('*', Regexp.last_match)}" }
s.gsub!( /(?<l>.?)[aeiou](?<r>.?)/ ) do
$~[:l] + (@@replace).call + $~[:r]
end
s
end
def callback( replace, match )
raise "Error: Match is empty" if match.nil?
return replace.upcase
end
end
t = Test.new
puts t.transcribe('example')
有人可以告诉我,我做错了什么,或者这是一个错误吗?
我用Google搜索了它:ruby Regexp.last_match lambda,似乎$1
在不同的情况下存在错误,但我无法理解它是否与此相关。
答案 0 :(得分:1)
正则表达式全局变量(Regexp.last_match
只是$〜的访问者)根本不是真正的全局变量。来自last_match
的{{3}}
请注意,last_match是线程的本地 和做法的方法范围 模式匹配。
因此,当您的lambda在不同的方法中定义时,方法范围是不同的,因此它访问自己的私有Regexp.last_match,这是未设置的。最简单的事情可能是将Regexp.last_match
作为参数传递给你的lambda
答案 1 :(得分:0)
您可以将匹配作为参数传递给块
s.gsub!( /(?<l>.?)[aeiou](?<r>.?)/ ) do |match|
$~[:l] + (@@replace).call(match) + $~[:r]
end
这应该可以解决您的问题。
一般情况下,我不会像$~
那样使用魔法,除非它与正则表达式位于同一行。它使代码更具可读性。