【问题标题】:Ruby: Write to stdin and read from stdout?Ruby:写入标准输入并从标准输出读取?
【发布时间】:2013-10-10 18:08:10
【问题描述】:

我正在编写一个 ruby​​ 程序,它应该执行另一个程序,通过标准输入向它传递值,从标准输出读取响应,然后打印响应。这是我目前所拥有的。

#!/usr/bin/env ruby

require 'open3'

stdin, stdout, stderr = Open3.popen3('./MyProgram')

stdin.puts "hello world!"

output = stdout.read
errors = stderr.read

stdin.close
stdout.close
stderr.close

puts "Output:"
puts "-------"
puts output
puts "\nErrors:"
puts "-------"
puts errors

我在这里肯定做错了 - 当我运行它时,它似乎在等待我输入文本。我不想收到任何提示 - 我想启动 ./MyProgram,传入 "hello world!",取回响应,然后在屏幕上打印响应。我该怎么做?

编辑

以防万一,MyProgram 基本上是一个程序,它会一直运行到 EOF,读取和打印内容。

【问题讨论】:

  • ./MyProgram 包含什么代码?
  • 你能做到p Open3.popen3('./MyProgram')吗?
  • 问题通常是子程序想要完全读取它的 STDIN,然后再尝试处理它读取的内容并输出结果。这意味着您必须关闭您的 STDIN 句柄,该句柄将传递给孩子,然后孩子知道可以完成其处理。这类似于父代码在完成处理之前将文件读取到末尾。

标签: ruby


【解决方案1】:

在读取输出之前尝试关闭标准输入。这是一个例子:

require 'open3'
Open3.popen3("./MyProgram") do |i, o, e, t|
  i.write "Hello World!"
  i.close
  puts o.read
end

这是使用Open3::capture3 的更简洁的编写方式:(注意,未经测试!)

o, e, s= Open3.capture3("./MyProgram", stdin_data: "Hello World!")
puts o

【讨论】:

    【解决方案2】:

    简单的工作方式:

    require 'open3'
    
    out, err, status = Open3.capture3("./parser", stdin_data: "hello world")
    
    out # string with standard output
    err # string with error output
    status.success? # true/false
    status.exitstatus # 0 / 1 / ...
    

    更多示例,包括发送二进制输入:https://ruby-doc.org/stdlib-2.6.3/libdoc/open3/rdoc/Open3.html#method-c-capture3

    【讨论】: