1

I am pretty sure that all of you know the bash pipelines. What I am trying to do is to read the output from one ruby script and put it as input into other ruby script

here is what I successfully accomplished so far:

first file to generate the output

#one.rb

puts "hello"

and the second file to handle the input

#two.rb

msg = gets.chomp
IO.write(File.dirname(__FILE__)+'\out.txt',msg)

now, the cygwin command (or linux) (side question: can this be done as well in windows cmd or powershell?)

ruby one.rb | ruby two.rb

and voila, the out.txt file is created, filled with string hello.

However, when I try it to do it in the cycle or handling some stream of data, like 10.times puts 'hello' and the in cycle to read it, it did not work. Can somebody please help me to accomplish this or show me the way how can i do that? I have only find some python question but it was for something different and some bash-like-way.

Thank you!

user_pruser
  • 422
  • 2
  • 13

3 Answers3

3

Instead of reading just one line (msg = gets.chomp) you need to iterate through the lines of stdin

$stdin.each_line do |msg|
  # ...
end

This does not wait for the entire output to be generated, it will process the stream as lines are printed by the first process (ignoring buffering).

For example, with these two scripts

# one.rb
i = 0
loop { puts i += 1 }

# two.rb
$stdin.each_line { |msg| puts "#{msg.chomp}!" }

The first has infinite output, but you will still see output when you run

ruby one.rb | ruby two.rb
Max
  • 21,123
  • 5
  • 49
  • 71
  • Thank you for your answer, but can you ensure me that it process the stream as it goes (process the lines as they are generated) or it process the whole output after it is generated? – user_pruser Jul 09 '15 at 06:39
0

You need to wait until STDIN sends an EOF in the second script.

Try:

#two.rb
msg = ""
while line = gets
  msg += line.chomp
end
IO.write(File.dirname(__FILE__)+'\out.txt',msg)

If the fist script contains 10.times { puts "hello" } you'll get:

hellohellohellohellohellohellohellohellohellohello
arco444
  • 22,002
  • 12
  • 63
  • 67
  • Thank you for your answer, but can you ensure me that it process the stream as it goes (process the lines as they are generated) or it process the whole output after it is generated? – user_pruser Jul 09 '15 at 06:39
-1

To read all the input, in two.rb change

msg = gets.chomp

to

msg = $stdin.read.chomp

If you want to read line-by-line, add some command line flags:

ruby -n two.rb

and two.rb becomes

  BEGIN {out = File.open(File.dirname(__FILE__)+"/out.txt", "w")}
  out.write $_

Using / instead of \ is OK on Windows.

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • Reading the entire stdin stream into memory is not a good idea. – Max Jul 08 '15 at 14:37
  • Sorry for the downvote, but your code uses a lot of Perlisms that are widely frowned upon in the Ruby community. – Max Jul 08 '15 at 17:33
  • Hey @max, I've been hiding in a corner licking my wounds ;) Sincerely, can you direct me to some place so I can learn about Ruby community standards? – glenn jackman Jul 30 '15 at 18:43
  • 1
    There's no official style guide for Ruby, but [this one](https://github.com/bbatsov/ruby-style-guide) reflects most of the practices adopted by the community. – Max Jul 30 '15 at 19:20