我在网上某处看到了这段代码:
ruby -pe 'gsub /^\s*|\s*$/, ""'
显然,这段代码会从STDIN的每一行中删除前导和尾随空格。
我理解正则表达式和替换,没有问题,但我没有得到的是方法gsub
如何接收一个对象来处理。我了解-p
标记在while gets; print; ... ; end
块中包含了整个内容,但是 gsub
如何接收字符串以对其进行操作?至少,它不应该是$_.gsub(..)
而是吗?当前输入行如何“神奇地”传递给gsub
?
这些类似Perl的单行代码是否以稍微不同的方式解释?我正在寻找与传统的基于脚本的Ruby代码的差异的一般概念。我恐怕没有找到一套全面的资源。
答案 0 :(得分:6)
事实证明,这是一个在Kernel上定义的实例方法,只有在使用-p或-n标志时才会神奇地启用它。
ruby -pe 'puts method(:gsub);'
#<Method: Object(Kernel)#gsub>
请参阅文档here。
我找到的其他神奇方法有chop
,print
和sub
。
神奇的方法都隐含地发送到$_
。
答案 1 :(得分:0)
易:
class Object
def gsub(*args, &block)
$_.gsub(*args, &block)
end
end
由于每个对象都是Object
的实例(好吧,几乎每个对象),现在每个对象都有一个gsub
方法。所以,你可以打电话给
some_object.gsub('foo', 'bar')
在任何对象上,它只会起作用。因为你调用它的是什么对象并不重要,因为它实际上并没有对该对象做任何事情,你也可以在self
上调用它:
self.gsub('foo', 'bar')
当然,由于self
是隐式接收器,因此与
gsub('foo', 'bar')
对于这样的方法,它实际上并不依赖于接收者,并且出于方便的原因只被添加到Object
类,因此将它们private
设为Kernel
是一种常见的约定。你不能用一个明确的接收者不小心打电话给他们然后以某种方式混淆思考这个方法对接收者做了什么。
此外,通常将这些方法(实际上用于过程而非方法,即完全独立于其接收器)放入{ {1}} mixin,混合到Object
而不是直接放入Object
类,以区别于每个对象可用的方法,但实际上做取决于它内部状态,例如Object#class
,Object#to_s
等。
module Kernel
private
def gsub(*args, &block)
$_.gsub(*args, &block)
end
end
以这种方式定义的其他方法,您可能已经遇到require
,load
,puts
,print
,p
, gets
,loop
,raise
,rand
,throw
,catch
,lambda
,proc
,{{ 1}},eval
,Array
,Integer
等。