是的。而且很容易向自己测试/证明。在命令行尝试这个:
ruby -e 'puts "foo"' > test.out
cat test.out
输出将是:
foo
Ruby 使用 STDOUT 通道输出到控制台。然后操作系统将该 STDOUT 重定向到“test.out”。
尝试一下:
ruby -e 'STDOUT.puts "foo"' > test.out
你会得到相同的结果。
如果我们这样做:
ruby -e 'STDERR.puts "foo"' > test.out
foo
cat test.out
您将在文件中看不到任何内容,但“foo”将被写入 STDERR 通道上的控制台。
Ruby 定义$stdout
作为一个全球性的人,你可以改变,并且STDOUT
作为一个常数,你不应该改变它。相似地,$stderr
and STDERR
可用。
现在,这就是它变得有趣的地方,并证明了你的问题。尝试这个:
ruby -e '$stdout = STDERR; puts "foo"' > test.out
你会得到与我输出相同的结果STDERR
,因为,在puts
正在使用该值$stdout
选择输出流,并写入STDERR。当解释器启动时,Ruby 从操作系统中获取这些流值,并在脚本运行时记住这些值。你可以改变它们如果需要的话当解释器退出时,Ruby 会忘记这些设置,并在下一次将其自身重置为正常状态。
你不应该依赖隐含的/看不见的改变行为$stdout
不过,因为这会导致代码非常混乱。相反,我强烈建议使用显式STDERR.puts
任何时候你写到 STDERR 和一个裸puts
用于正常输出到 STDOUT。如果您将两者的输出混合在一起,那么使用可能会更清楚STDOUT.puts
and STDERR.puts
,但这就是你的决定。
现在,IRB 与解释器中运行的常规脚本相同,只要使用$stdout
因此将 IRB 中的输出写入$stdout
工作原理相同:
irb(main):001:0> $stdout
#<IO:<STDOUT>>
irb(main):002:0> $stderr
#<IO:<STDERR>>
And:
irb(main):003:0> $stdout.puts 'foo'
foo
nil
irb(main):004:0> $stderr.puts 'foo'
foo
nil
最后:
irb(main):007:0> $stdout.isatty
true
irb(main):008:0> $stdout.isatty
true
除非我们看得更低一些,否则我们无法真正看出任何区别。它们都是 TTY 通道,具有标准 STDOUT 和 STDERR 通道号:
irb(main):009:0> $stdout.fileno
1
irb(main):010:0> $stderr.fileno
2
希望这有助于“解释它”。
我刚刚意识到 IRB 报告的回报值puts
可能会让您感到困惑,导致您认为 STDOUT 正在更改。那nil
返回与 STDOUT 或 STDERR 无关。这是因为puts
返回 nil,由 IRB 尽职尽责地报告。