【问题标题】:dropping user to IRB after reading from pipe从管道读取后将用户放到 IRB
【发布时间】:2011-01-03 14:36:25
【问题描述】:

我有这个脚本,它在执行时将用户放到 IRB 会话中。

一切都好,但是当我使用 *nix 管道获取输入时(例如使用 cat),IRB 会话立即结束。

我可以将脚本(我们称之为 myscript.rb)简化为以下内容:

需要'irb' 如果 $stdin.stat.size > 0 @text = $stdin.read 别的 @text="什么都没有" 结尾 ARGV.清除 IRB.start

当像 ruby myscript.rb 这样执行时,我最终进入 IRB 会话(如预期的那样)。

但是(假设foo.txt 存在于cwd 中):cat foo.txt | ruby myscript.rb 将只打印 IRB 提示,然后关闭 IRB 会话(我被丢弃到 $bash)。

任何已知的解决方法或想法?

顺便说一句:它在 ruby​​ 1.8.7 和 1.9.2 上具有相同的行为。

【问题讨论】:

    标签: ruby irb


    【解决方案1】:

    我认为您的问题是,当您通过管道传输到脚本时,STDIN 将是您文件中的流,因此当您启动 IRB 时,它将从同一个流中读取,但请注意它已结束,然后退出,只是就像你输入 ctrl-D 时一样(这是一个手动的文件结束信号)。

    您可以像这样重新打开 STDIN 以从 tty(即键盘)读取:

    STDIN.reopen(File.open('/dev/tty', 'r'))
    

    但这对我来说有点奇怪,我没有得到正确的 IRB 提示。不过,IRB 有效。

    【讨论】:

    • 看起来这是问题所在,重新打开 $stdin 将创建一个默认(我猜)IRB(没有提示,.irbrc 未读取等等)。
    • 另一方面,在 $stdin 上倒带或 seek(0) 将不起作用(是 tty)。
    • seek(0) 不起作用是什么意思,为什么需要它?如果我不清楚,我的意思是您在 IRB.start 之前重新打开 stdin。
    • 而不是重新打开我试图做 $stdin.rewind (或 .seek)。你说的很清楚,谢谢你的回答。
    • +1 我一直想知道如何从标准输入中读取一个或多个 EOF。您可能需要 File.open 的块形式,这样您就不会泄漏文件描述符。
    【解决方案2】:

    @Theo 发现了问题。

    此外,在 IRB.start 之前要求 irb 将修复缺少的 IRB 设置。最后,代码是这样的:

    如果 $stdin.stat.size > 0 @text = $stdin.read $stdin.reopen(File.open("/dev/tty", "r")) 别的 @text="什么都没有" 结尾 需要'irb' ARGV.清除 IRB.start

    【讨论】:

      【解决方案3】:

      $stdin.read 在 IRB 有机会读取您的输入之前读取它(如果您试图强制 IRB 执行来自标准输入的命令)。

      【讨论】:

      • foo.txt 只是一个纯文本文件。
      猜你喜欢
      • 1970-01-01
      • 2022-11-10
      • 2016-06-05
      • 1970-01-01
      • 2014-03-13
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      • 2019-10-18
      相关资源
      最近更新 更多