How can I capture STDOUT to a string?
1 2 | puts"hi" puts"bye" |
我希望将stdout存储到目前为止的代码中(在本例中,hi bye存储到变量say'result'并打印它)
1 | puts result |
我这样做的原因是我已经在我的Ruby代码中集成了一个R代码,当R代码运行时,输出被提供给stdout,但是在代码中不能访问ouput来做一些评估。抱歉,如果这让人困惑的话。所以"看跌结果"一行应该给我打个招呼再见。
一个将stdout捕获到字符串中的方便函数…
下面的方法是一个方便的通用工具,用于捕获stdout并将其作为字符串返回。(我经常在要验证打印到stdout的内容的单元测试中使用此方法。)请特别注意,使用
1 2 3 4 5 6 7 8 | def with_captured_stdout original_stdout = $stdout $stdout = StringIO.new yield $stdout.string ensure $stdout = original_stdout end |
例如:
1 2 3 4 5 6 7 8 | >> str = with_captured_stdout { puts"hi"; puts"bye"} =>"hi bye " >> print str hi bye => nil |
将标准输出重定向到Stringio对象
您当然可以将标准输出重定向到变量。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # Set up standard output as a StringIO object. foo = StringIO.new $stdout = foo # Send some text to $stdout. puts 'hi' puts 'bye' # Access the data written to standard output. $stdout.string # =>"hi bye " # Send your captured output to the original output stream. STDOUT.puts $stdout.string |
实际上,这可能不是一个好主意,但至少现在你知道这是可能的。
如果项目中有可用的ActiveSupport,您可以执行以下操作:
1 2 3 | output = capture(:stdout) do run_arbitrary_code end |
有关
您可以通过在反勾号内调用R脚本来实现这一点,如下所示:
1 2 | result = `./run-your-script` puts result # will contain STDOUT from run-your-script |
有关在Ruby中运行子进程的详细信息,请查看此堆栈溢出问题。
出于最实际的目的,您可以将响应
在这个示例中,我使用来自stdlib的修改后的队列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | class Captor < Queue alias_method :write, :push def method_missing(meth, *args) false end def respond_to_missing?(*args) true end end stream = Captor.new orig_stdout = $stdout $stdout = stream puts_thread = Thread.new do loop do puts Time.now sleep 0.5 end end 5.times do STDOUT.print">> #{stream.shift}" end puts_thread.kill $stdout = orig_stdout |
如果您希望积极地对数据采取行动,而不仅仅是在任务完成后查看数据,那么就需要这样的东西。如果多个线程试图同时同步读写,那么使用Stringio或文件会有问题。
对于RinRuby,请知道R有
1 2 3 4 5 | R.eval <<EOF captured <- capture.output( ... ) EOF puts R.captured |
1 2 3 4 | assert_output"Registrars processed: 1 " do puts 'Registrars processed: 1' end |
断言输出
或者,如果您真的需要捕获它,可以使用
1 2 3 4 5 6 7 | out, err = capture_io do puts"Some info" warn"You did a bad thing" end assert_match %r%info%, out assert_match %r%bad%, err |
捕获器
归功于@girasquid的回答。我将其修改为单个文件版本:
1 2 3 4 5 6 7 8 | def capture_output(string) `echo #{string.inspect}`.chomp end # example usage response_body ="https:\\x2F\\x2Faccounts.google.com\\x2Faccounts" puts response_body #=> https:\x2F\x2Faccounts.google.com\x2Faccounts capture_output(response_body) #=> https://accounts.google.com/accounts |