我想知道Ruby使用的输出流在命令行打印这些东西:
irb(main):001:0> a="test"
=> "test"
irb(main):002:0> puts a
test
=> nil
irb(main):003:0> a
=> "test"
Run Code Online (Sandbox Code Playgroud)
是$stdout用于irb(main):002:0>和irb(main):003:0>?而且,$stdout这两次调用之间的价值是否有任何变化?
还有,有人可以指出我从这些东西打印/写入的Ruby源代码?
是.并且很容易测试/证明自己.在命令行尝试此操作:
ruby -e 'puts "foo"' > test.out
cat test.out
Run Code Online (Sandbox Code Playgroud)
输出将是:
foo
Run Code Online (Sandbox Code Playgroud)
Ruby使用STDOUT通道输出到控制台.操作系统然后将该STDOUT重定向到"test.out".
尝试使用:
ruby -e 'STDOUT.puts "foo"' > test.out
Run Code Online (Sandbox Code Playgroud)
你会得到相同的结果.
如果我们这样做:
ruby -e 'STDERR.puts "foo"' > test.out
foo
cat test.out
Run Code Online (Sandbox Code Playgroud)
您将在文件中看不到任何内容,但"foo"将被写入STDERR频道的控制台.
Ruby定义$stdout为可以更改的全局变量,并且STDOUT作为常量,您不应该更改.同样,$stderr并且STDERR可用.
现在,这里变得有趣,并证明你的问题.试试这个:
ruby -e '$stdout = STDERR; puts "foo"' > test.out
Run Code Online (Sandbox Code Playgroud)
并且你将得到与输出时相同的结果STDERR,因为,at puts使用值$stdout来选择输出流,并写入STDERR.当解释器启动时,Ruby会从操作系统中获取这些流值,并在脚本运行时记住这些值.如果需要,您可以更改它们,Ruby将在解释器退出时忘记这些设置,并在下次将其自身重置为正常状态.
你不应该依赖于改变的隐含/不可见行为$stdout,因为这会导致真正令人困惑的代码.相反,我强烈建议STDERR.puts您在写入STDERR时使用显式,并将puts正常输出裸露到STDOUT.如果你交缠输出到两个,那么它很可能是更清晰的使用STDOUT.puts和STDERR.puts,但这是你的电话.
现在,IRB与在解释器中运行的常规脚本相同,只要$stdout在IRB中使用这样的写输出就$stdout可以了:
irb(main):001:0> $stdout
#<IO:<STDOUT>>
irb(main):002:0> $stderr
#<IO:<STDERR>>
Run Code Online (Sandbox Code Playgroud)
和:
irb(main):003:0> $stdout.puts 'foo'
foo
nil
irb(main):004:0> $stderr.puts 'foo'
foo
nil
Run Code Online (Sandbox Code Playgroud)
最后:
irb(main):007:0> $stdout.isatty
true
irb(main):008:0> $stdout.isatty
true
Run Code Online (Sandbox Code Playgroud)
在我们看起来稍低之前,我们无法区分任何差异; 它们都是TTY频道,标准的STDOUT和STDERR频道号码:
irb(main):009:0> $stdout.fileno
1
irb(main):010:0> $stderr.fileno
2
Run Code Online (Sandbox Code Playgroud)
希望这有助于'摒弃它.
我刚刚意识到IRB报告的返回值puts可能让您感到困惑,导致您认为STDOUT正在发生变化.这nil将返回无关与stdout或stderr.这是因为puts返回nil,由IRB尽职尽责地报告.