所需的所有信息都在Popen3 文档中,但您必须阅读所有内容并仔细查看示例。您还可以从Process 文档中收集有用的信息。
也许这会“更好地解释它:
require 'open3'
captured_stdout = ''
captured_stderr = ''
exit_status = Open3.popen3(ENV, 'date') {|stdin, stdout, stderr, wait_thr|
pid = wait_thr.pid # pid of the started process.
stdin.close
captured_stdout = stdout.read
captured_stderr = stderr.read
wait_thr.value # Process::Status object returned.
}
puts "STDOUT: " + captured_stdout
puts "STDERR: " + captured_stderr
puts "EXIT STATUS: " + (exit_status.success? ? 'succeeded' : 'failed')
运行输出:
STDOUT: Wed Jun 12 07:07:12 MST 2013
STDERR:
EXIT STATUS: succeeded
注意事项:
- 你经常不得不
close
流stdin
。如果被调用的应用程序期望 STDIN 上的输入,它将挂起,直到它看到流关闭,然后将继续其处理。
stdin
, stdout
,stderr
是 IO 句柄,因此您必须阅读IO 类文档以了解可用的方法。
- 您必须
stdin
使用puts
, print
or write
, and read
or gets
from stdout
and输出stderr
。
exit_status
不是字符串,它是 Process::Status 类的实例。你可以尝试从它的to_s
版本中解析,但不要。而是使用访问器查看它返回的内容。
- 我传入了
ENV
哈希,因此子程序可以访问父程序看到的整个环境。没有必要这样做;相反,如果您不希望孩子可以访问所有内容,则可以为孩子创建一个简化的环境,或者您可以通过更改值来扰乱孩子对环境的看法。
- 问题中发布的代码
stdout.read("TX.*\s+(\d+)\s+")
是,嗯......胡说八道。我不知道你从哪里得到的,因为 Ruby 的IO#read或IO.read的 IO 类中没有记录任何类似的东西。
capture3
如果您不需要写入被调用代码的 STDIN,它会更容易使用:
require 'open3'
stdout, stderr, exit_status = Open3.capture3('date')
puts "STDOUT: " + stdout
puts "STDERR: " + stderr
puts "EXIT STATUS: " + (exit_status.success? ? 'succeeded' : 'failed')
哪个输出:
STDOUT: Wed Jun 12 07:23:23 MST 2013
STDERR:
EXIT STATUS: succeeded
使用正则表达式从字符串中提取值是很简单的,并且在Regexp 文档中有很好的介绍。从最后一个代码示例开始:
stdout[/^\w+ (\w+ \d+) .+ (\d+)$/]
puts "Today is: " + [$1, $2].join(' ')
哪个输出:
Today is: Jun 12 2013
那是使用String.[]
非常灵活的方法。
另一种方法是使用“命名捕获”:
/^\w+ (?<mon_day>\w+ \d+) .+ (?<year>\d+)$/ =~ stdout
puts "Today is: #{ mon_day } #{ year }"
输出相同的东西。命名捕获的缺点是它们速度较慢,因为我认为有点方便。
"TX So and so: 28"[/\d+$/]
=> "28"