在Ruby中,$stdout和STDOUT的区别是什么?

105
在Ruby中,$stdout(前面带有美元符号)和STDOUT(全大写)有什么区别?在进行输出重定向时,应该使用哪个并为什么?对于$stderrSTDERR也是如此。 编辑:刚刚发现一个相关问题

可能是什么是Ruby中STDIN和$stdin的区别?的重复问题。 - the Tin Man
@theTinMan 有点重复。但是必须注意的是,虽然 $stdoutSTDOUT$stdinSTDIN 之间的差异是对称的,但是 $stdout$>$stdin$< 之间的差异并不是。 - skalee
3个回答

121

$stdout是一个全局变量,表示当前的标准输出。 STDOUT是一个常量,表示标准输出,通常是$stdout的默认值。

由于STDOUT是一个常量,不应该重新定义它,但是你可以重新定义$stdout而不会出现错误/警告(重新定义STDOUT将引发警告)。例如,你可以这样做:

$stdout = STDERR

同样适用于$stderrSTDERR


因此,为了回答您问题的另一部分,请使用全局变量来重定向输出,而不是常量。只需小心在代码中进一步更改它,重新定义全局变量可能会影响应用程序的其他部分。


3
实际上,如果你想重定向输出,你应该使用 $> 这个默认的输出流,而不是 $stdout - Jörg W Mittag
11
刚在另一个问题的评论中发现一条消息,说$stdout$>是别名,因此重新分配其中之一会影响另一个。 - jrdioko
9
你说得对。显然,我不仅每天学到新东西,还会每天忘记一些东西 :-) - Jörg W Mittag
2
阅读更多后,听起来最好使用IO#reopen而不是简单的赋值。 - jrdioko
@jrdioko,你为什么认为在处理 $stdout 时使用 IO#reopen 更好呢?我完全不同意这种观点。$stdout.reopen 方法会改变它的接收者,如果你没有在重新分配 $stdout 之前对 STDOUT 进行重新分配,那么它也会影响到 STDOUT。它们并不是同义词,由于赋值而持有不同的值并不是什么坏事,通过重新打开 STDOUT,你正在破坏它的目的。 - skalee

12

$stdoutSTDOUT 有不同的含义。 Ruby 的文档 对此问题非常清楚:

  • $stdout – 当前标准输出。
  • STDOUT – 标准输出。$stdout 的默认值。

当您想要写入标准输出时,实际上是指当前标准输出,因此应写入 $stdout

STDOUT 也不无用处。它存储了 $stdout 的默认值。如果您重新分配了 $stdout,则可以使用 $stdout = STDOUT 将其恢复为先前的值。

此外,还有一个预定义变量:

  • $> – print、printf 的默认输出, 默认情况下是 $stdout

然而,在 Ruby 2.3 中,它似乎只是 $stdout 的别名。重新分配 $stdout 会更改 $> 的值,反之亦然。


6
  • STDOUT 是一个全局常量,所以不应该被更改。
  • $stdout 是一个预定义变量,因此可以被更改。

如果你正在使用 shell 进行重定向:

$ ruby test.rb > test.log

如果您的脚本在执行之前已经确定了文件描述符,则使用哪个文件描述符都无所谓。

但是,如果您尝试从Ruby脚本内部更改操作系统的STDOUT文件描述符,例如根据当前星期几将输出发送到一组旋转的日志文件中,则需要确保使用$stdout


5
"STDOUT是一个全局常量,因此它不会改变"。它是一个常量,但可以被更改,但会发出警告。 `STDOUT = $ stderr (irb):1: warning: already initialized constant STDOUT
STDOUT #=> #<IO:<STDERR>>`
- the Tin Man
啊,是的,应该说“所以它不应该被改变”。谢谢! - shakerlxxv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接