How can I write STDOUT to a string?

puts "hi" puts "bye" 

I want to keep the STDOUT of the code so far (in this case, hi \ nbye into the variable say "result" and print it)

 puts result 

The reason I do this is to integrate the R code into my Ruby code, the output of which is passed to STDOUT as the R code runs, but the output from this code may not be available inside the code to perform some evaluations. Sorry if this is confusing. So the line "puts result" should give me greetings and goodbye.

+34
ruby stdio
Feb 20 '13 at 18:32
source share
9 answers

Redirect standard output to a StringIO object

Of course, you can redirect standard output to a variable. For example:

 # 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 

In practice, this is probably not a good idea, but at least now you know that it is possible.

+42
Feb 20 '13 at 19:25
source share

Convenient function for capturing standard output in a string ...

The following method is a convenient general-purpose tool for capturing standard output and returning it as a string. (I often use this in unit tests where I want to check something printed on standard output.) Pay particular attention to using the ensure condition to restore $ standard output (and to avoid surprise):

 def with_captured_stdout original_stdout = $stdout # capture previous value of $stdout $stdout = StringIO.new # assign a string buffer to $stdout yield # perform the body of the user code $stdout.string # return the contents of the string buffer ensure $stdout = original_stdout # restore $stdout to its previous value end 

For example:

 >> str = with_captured_stdout { puts "hi"; puts "bye"} => "hi\nbye\n" >> print str hi bye => nil 
+63
Apr 01 '14 at 5:50
source share

If active support is available in your project, you can do the following:

 output = capture(:stdout) do run_arbitrary_code end 

More information about Kernel.capture can be found here.

+9
Jul 01 '14 at 9:05
source share

You can do this by accessing your R script inside backticks, for example:

 result = `./run-your-script` puts result # will contain STDOUT from run-your-script 

For more information on running subprocesses in Ruby, check out this stack overflow question .

+8
Feb 20 '13 at 18:35
source share

For most practical purposes, can you put something in $stdout that responds to write , flush , sync , sync= and tty? .

In this example, I am using a modified Queue from stdlib.

 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 

You need something like this if you want to actively act on the data, and not just look at it after completing the task. Using StringIO or a file will be problematic with multiple threads trying to synchronize read and write at the same time.

+1
Jun 09 '17 at 12:07 on
source share

Minitest version:




assert_output , if you need to make sure that some output is generated:

 assert_output "Registrars processed: 1\n" do puts 'Registrars processed: 1' end 

assert_output




or use capture_io if you really need to capture it:

 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 

capture_io

TG45 itself is available in any version of Ruby, starting from 1.9.3 .

0
Oct 02 '18 at 19:49
source share

For RinRuby, please know that R has capture.output :

 R.eval <<EOF captured <- capture.output( ... ) EOF puts R.captured 
0
Jan 05 '19 at 18:24
source share

Capturing stdout (or stderr) for Ruby code and subprocesses

 # 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 

I got inspiration from Jon .

0
Aug 07 '19 at 12:47
source share

Credit answer @girasquid. I changed it to one version of the file:

 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 
-one
Sep 28 '16 at 10:26
source share



All Articles