Ruby 中 $stdout 和 STDOUT 的区别
Posted
技术标签:
【中文标题】Ruby 中 $stdout 和 STDOUT 的区别【英文标题】:Difference between $stdout and STDOUT in Ruby 【发布时间】:2011-10-04 01:02:39 【问题描述】:在 Ruby 中,$stdout
(前面有一个美元符号)和STDOUT
(全部大写)有什么区别?在进行输出重定向时,应该使用哪个,为什么? $stderr
和 STDERR
也是如此。
编辑:刚刚找到related question。
【问题讨论】:
What is the difference between STDIN and $stdin in Ruby?的可能重复 @theTinMan 有点重复。但是必须注意,虽然$stdout
和STDOUT
与$stdin
和STDIN
之间的差异是对称的,但$stdout
和$>
与$stdin
和$<
之间的差异不是。
【参考方案1】:
$stdout
是一个代表当前标准输出的全局变量。 STDOUT
是一个代表标准输出的常量,通常是$stdout
的默认值。
STDOUT
是一个常量,您不应该重新定义它,但是,您可以重新定义 $stdout
而不会出现错误/警告(重新定义 STDOUT
会引发警告)。例如,你可以这样做:
$stdout = STDERR
$stderr
和 STDERR
也是如此
因此,要回答您问题的另一部分,请使用全局变量而不是常量来重定向输出。请注意在您的代码中进一步更改它,重新定义全局变量可能会影响应用程序的其他部分。
【讨论】:
其实,如果你想重定向输出,你可能应该使用默认输出流$>
,而不是$stdout
。
刚找到一个comment on another question,上面写着$stdout
和$>
是别名,所以重新分配一个会影响另一个。
@jrdioko:你是对的。显然,我不仅每天都学到新东西,而且每天都会忘记一些东西:-)
而且阅读更多,听起来最好使用IO#reopen 而不是简单的赋值。
@jrdioko 为什么你认为在$stdout
的情况下使用IO#reopen
更好?我完全不同意这种观点。 $stdout.reopen
方法 mutates 它的接收者,如果您之前没有重新分配 $stdout
,这也会影响 STDOUT
。它们并不意味着是同义词,当它们由于分配而持有不同的值时并没有什么不好,并且通过重新打开 STDOUT
你打破了它的目的。【参考方案2】:
STDOUT
是一个全局常量,因此不应更改。
$stdout
是预定义变量,因此可以更改。
如果你使用shell做重定向:
$ ruby test.rb > test.log
那么在你的脚本执行之前,你使用哪一个作为脚本的文件描述符并不重要。
但是,如果您尝试在 Ruby 脚本中更改操作系统 STDOUT 的文件描述符,例如根据一周中的当前日期将输出发送到一组轮换的日志文件,那么您需要确保您使用$stdout
。
【讨论】:
“STDOUT 是一个全局常量,所以它不会改变”。它是一个常数,可以更改,但会发出警告。STDOUT = $stderr (irb):1: warning: al#=> #<IO:<STDERR>>constant STDOUT >> STDOUT #=> #<IO:<STDERR>>
啊,是的,所以应该说“所以不应该改变”。谢谢!【参考方案3】:
$stdout
和 STDOUT
有不同的含义。 Ruby's documentation 非常清楚这个话题:
$stdout
– 当前标准输出。STDOUT
– 标准输出。 $stdout 的默认值。
当您要写入标准输出时,您实际上是指当前标准输出,因此您应该写入$stdout
。
STDOUT
也不是没用的。它存储$stdout
的默认值。如果您曾经重新分配 $stdout
,那么您可以使用 $stdout = STDOUT
将其恢复为之前的值。
此外,还有一个预定义变量:
$>
- print 的默认输出 printf,默认为$stdout
。
然而它在 Ruby 2.3 中看起来只是作为$stdout
的别名。重新分配 $stdout
会更改 $>
的值,反之亦然。
【讨论】:
以上是关于Ruby 中 $stdout 和 STDOUT 的区别的主要内容,如果未能解决你的问题,请参考以下文章
ruby stream system命令输出到STDOUT(ruby)