我理解如下:
$ ruby -e "p 'abc'.sub('a','A').sub('b', 'B')"
"ABc"
我也同意以下几点:
echo abc | ruby -p -e "sub('a','A');sub('b', 'B')"
ABc
但是:
echo abc | ruby -p -e "sub('a','A').sub('b', 'B')"
Abc
我希望结果也是"ABc",为什么不是呢?第二个sub('b', 'B')
不工作.
我理解如下:
$ ruby -e "p 'abc'.sub('a','A').sub('b', 'B')"
"ABc"
我也同意以下几点:
echo abc | ruby -p -e "sub('a','A');sub('b', 'B')"
ABc
但是:
echo abc | ruby -p -e "sub('a','A').sub('b', 'B')"
Abc
我希望结果也是"ABc",为什么不是呢?第二个sub('b', 'B')
不工作.
这两种情况看起来很相似,但实际上您运行的方法与其中的Ruby core库不同:
在第一种情况下,即sub('a','A');sub('b', 'B')
:
运行这两个sub
时没有指定显式接收器,因此调用方法Kernel#sub
.Ruby文档介绍了这种方法:
sub(pattern, replacement)
→$_
相当于
$_.sub(args)
,但如果发生替换,将更新$_
.仅当指定了-p/-n命令行选项时可用.
因此,在第一个示例中,您实际上调用了Kernel#sub
次,每次调用之后,$_
都会更新.因此,$_
是在执行了第二sub
之后的ABc.在-e
提供的整个表达式的末尾(即在-p
选项提供的隐式循环的末尾),打印$_
的值,您可以看到ABc.
在第二个示例中,即.
sub('a','A').sub('b', 'B')
与之前一样,第一个sub
也是Kernel#sub
.它可以将字符串转换为Abc,也可以将$_
设置为Abc.然而,第二sub
现在确实具有显式接收器(由第一sub
产生的字符串),并且在这种情况下,执行方法String#sub
.此方法生成ABc,但与Kernel#sub
不同,它执行not更新$_
.因此,$_
仍然设置为Abc,这就是您所看到的输出.