puts "hi"
puts "bye"
到目前为止,我想存储代码的STDOUT(在这种情况下,hi \ nbye变成一个变量,说'结果'并打印出来)
puts result
我这样做的原因是我已经将R代码集成到我的Ruby代码中,当R代码运行时,其输出被提供给STDOUT,但是在代码内部无法访问输出以进行一些评估。对不起,如果这令人困惑。因此,“放置结果”这一行应该让我高兴和再见。
答案 0 :(得分:60)
以下方法是一个方便的通用工具,用于捕获stdout并将其作为字符串返回。 (我经常在单元测试中使用它来验证打印到stdout的内容。)特别注意使用ensure
子句来恢复$ stdout(并避免惊讶):
def with_captured_stdout
original_stdout = $stdout
$stdout = StringIO.new
yield
$stdout.string
ensure
$stdout = original_stdout
end
所以,例如:
>> str = with_captured_stdout { puts "hi"; puts "bye"}
=> "hi\nbye\n"
>> print str
hi
bye
=> nil
答案 1 :(得分:41)
您当然可以将标准输出重定向到变量。例如:
# 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\nbye\n"
# Send your captured output to the original output stream.
STDOUT.puts $stdout.string
在实践中,这可能不是一个好主意,但至少现在你知道它是可能的。
答案 2 :(得分:9)
如果您的项目中有activesupport,您可以执行以下操作:
output = capture(:stdout) do
run_arbitrary_code
end
有关Kernel.capture
的更多信息,请访问here
答案 3 :(得分:8)
你可以通过在反引号中调用R脚本来实现这一点,如下所示:
result = `./run-your-script`
puts result # will contain STDOUT from run-your-script
有关在Ruby中运行子进程的更多信息,请查看this Stack Overflow question。
答案 4 :(得分:1)
出于大多数实际目的,您可以将任何内容放入$stdout
,write
,flush
,sync
,sync=
和tty?
。
在此示例中,我使用stdlib中的修改后的Queue。
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或文件会导致多个线程同时尝试同步读取和写入时出现问题。
答案 5 :(得分:0)
Minitest
版本:
assert_output
,如果需要确保是否生成某些输出:
assert_output "Registrars processed: 1\n" do
puts 'Registrars processed: 1'
end
或如果确实需要捕获,请使用capture_io
:
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
从Minitest
到 1.9.3
本身在任何Ruby版本中都可用
答案 6 :(得分:0)
对于RinRuby,请注意R具有capture.output
:
R.eval <<EOF
captured <- capture.output( ... )
EOF
puts R.captured
答案 7 :(得分:0)
# capture_stream(stream) { block } -> String
#
# Captures output on +stream+ for both Ruby code and subprocesses
#
# === Example
#
# capture_stream($stdout) { puts 1; system("echo 2") }
#
# produces
#
# "1\n2\n"
#
def capture_stream(stream)
raise ArgumentError, 'missing block' unless block_given?
orig_stream = stream.dup
IO.pipe do |r, w|
# system call dup2() replaces the file descriptor
stream.reopen(w)
# there must be only one write end of the pipe;
# otherwise the read end does not get an EOF
# by the final `reopen`
w.close
t = Thread.new { r.read }
begin
yield
ensure
stream.reopen orig_stream # restore file descriptor
end
t.value # join and get the result of the thread
end
end
我从Zhon获得了灵感。
答案 8 :(得分:-1)
归功于@ girasquid的回答。我将其修改为单个文件版本:
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