【问题标题】:Difference between `STDIN` and `$stdin``STDIN` 和 `$stdin` 之间的区别
【发布时间】:2015-04-22 22:14:15
【问题描述】:

我想知道STDIN$stdin 之间是否有任何真正的区别。我在 irb 做:

STDIN == $stdin

然后返回true。它们只是同一事物的两个名称吗?还是有什么不同?

【问题讨论】:

标签: ruby


【解决方案1】:

来自Ruby globals

标准输入

标准输入。 $stdin 的默认值。

默认情况下它们是同一个对象。

[1] pry(main)> $stdin.object_id
=> 13338048
[2] pry(main)> STDIN.object_id
=> 13338048
[3] pry(main)> $stdin.object_id == STDIN.object_id
=> true

正如@shivam 评论的那样,$stdin 是一个全局变量,它可能被分配给不同的东西,而STDIN 是一个常量。

【讨论】:

  • 这并不完全正确。 $stdin = "asd", $stdin.object_id == STDIN.object_id # => false
  • @shivam 是的,我应该说“默认情况下”
  • 所以,如果我这样做 $stdout = File.open("test.log", "w") 那么 STDOUT 允许我将输出重定向回控制台?是这个主要原因还是有其他应用?
  • @NikitaLuparev 是的,它提供了一种重定向 putsgets 默认使用的输入和输出的方法。
【解决方案2】:

STDIN 是一个常量,因此如果您尝试替换它,您会收到一个红宝石警告。否则,这两个只是普通的 ruby​​ 变量,因为它们可以指向同一个对象(并且默认情况下),如果它们这样做,对一个变量做某事会影响另一个变量,但是如果你将其他东西分配给其中一个变量,它们会有所不同。

默认情况下,get 等标准 ruby​​ 方法将从 $stdin(不是 STDIN)读取。这意味着您可以为标准方法覆盖 $stdin$stdout$stderr),并使用常量版本来查看 $stdin$stdout$stderr 原来是什么。

请注意,覆盖 $stdin$stdout$stderr 不会影响新生成程序的标准流(实际文件描述符分别为 0、1 和 2)。为此,您需要在要更改的流上调用 IO#reopen,例如(假设常量版本没有被强制替换),

STDOUT.reopen("newfile") #Write all output to "newfile" including the output of newly spawned processes (`%x{}`,`system`, `spawn`, `IO.popen`, etc.)

现在通过重新打开,您只能将流替换为实际的操作系统级别的文件/文件描述符(例如,没有 StringIO),但如果您使用的是 UNIX,那么您可以使用操作系统做的事情不多 -级别文件(例如,您可以将它们更改为可以在程序的其他地方读取的管道)。

【讨论】:

    猜你喜欢
    • 2011-05-15
    • 2015-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    • 2014-01-15
    • 1970-01-01
    相关资源
    最近更新 更多