0

I try to run an external command in Ruby, and parse its output .

 IO.popen(command, :err=>[:child, :out]) {|ls_io|
  ls_io.each do |line| 
   print line   
 end
 }

This way of doing it works wonders… except when I parse the progress-output of a c-program that shows it progress to stdout with \r.

As long as the c-program has not outputted a \n (that is as long as it has not finished some long-operation), Ruby waits and sees nothing. Then when a \n is outputted, Ruby sees it all

1%\r2%\r3%\r…100%
task finished

I tried all of the many ways to call external commands (eg Calling shell commands from Ruby) ; but none seem to capture the progress. I also tried every opeartor such as STDOUT.sync = true, and the c-program does call fflush(stdout)

I finally found a workaroud. I do :

IO.popen(commande, :err=>[:child, :out]) {|ls_io|
while true
  byte=ls_io.read(1)
  if byte.nil?
    break
  end
   print byte
end
}

It's stupid… but it works.

Any more elegant way, and much more efficient way to do this ? Performance is terrible, as if the "refresh rate" was slow.

Community
  • 1
  • 1
MichaelC
  • 307
  • 2
  • 11

1 Answers1

0

Set the input record separator to "\r" right before your block (provided you know it in advance):

$/ = "\r"

Reference of global preset variables: http://www.zenspider.com/Languages/Ruby/QuickRef.html#pre-defined-variables

Kombajn zbożowy
  • 4,673
  • 1
  • 21
  • 49
  • thanks… but then there are also those \n I wanna catch. I just want to receive the output like I would if calling the command from a shell rather than from ruby ! – MichaelC Sep 19 '14 at 21:43