[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

piping input when shelling out

Caio Chassot

9/20/2006 12:10:00 AM

Hi all,

I want to use Kernel#system or one of its friends to manipulate some
data I have in a ruby string. Ideally, I'd want the executed command
to read the string from stdin, as if ruby had piped the data to it.
The data may be reasonably large. Any tips?

thanks

17 Answers

Paul Lutus

9/20/2006 12:42:00 AM

0

Caio Chassot wrote:

> Hi all,
>
> I want to use Kernel#system or one of its friends to manipulate some
> data I have in a ruby string. Ideally, I'd want the executed command
> to read the string from stdin, as if ruby had piped the data to it.
> The data may be reasonably large. Any tips?

Could you be a bit more clear? Do you want to write a program that will
cooperate with a stream? As in:

data_source | ruby-program | data_dest

Yes?

--
Paul Lutus
http://www.ara...

Caio Chassot

9/20/2006 12:49:00 AM

0


On 2006-09-19, at 21:45 , Paul Lutus wrote:

>
> Could you be a bit more clear? Do you want to write a program that
> will
> cooperate with a stream? As in:
>
> data_source | ruby-program | data_dest
>
> Yes?


No, from within a ruby program I want to call some shell command to
act on data stored in a ruby string, so, in the ruby program,
something like, in pseudoruby:

output = system('shell_cmd --params etc', :input => a_string)


Caio Chassot

9/20/2006 1:00:00 AM

0


On 2006-09-19, at 21:51 , Daniel N wrote:

>>
>> You could try using IO#popen The docs are at
>
> http://www.ruby-doc.org/core/classes/IO.ht...
>
> Hope this is what your after.

Looks like it. Thanks a lot.

Do you know if it places the exit code in $? ?

I wonder what happens if the subprocess is killed by the system?

I guess I'll run some tests, but if you happen to know the answers,
I'd be glad to hear them nonetheless.


Paul Lutus

9/20/2006 1:04:00 AM

0

Caio Chassot wrote:

>
> On 2006-09-19, at 21:45 , Paul Lutus wrote:
>
>>
>> Could you be a bit more clear? Do you want to write a program that
>> will
>> cooperate with a stream? As in:
>>
>> data_source | ruby-program | data_dest
>>
>> Yes?
>
>
> No, from within a ruby program I want to call some shell command to
> act on data stored in a ruby string, so, in the ruby program,
> something like, in pseudoruby:
>
> output = system('shell_cmd --params etc', :input => a_string)

Okay, try this:

--------------------------------

#!/usr/bin/ruby -w

s = "avast arlington always"

output = `echo #{s} | perl -pe "s/a/x/g"`

p output

--------------------------------

Output:

"xvxst xrlington xlwxys\n"

I want to emphasize there are a dozen ways to do this. This one happens to
be simple to understand. Another way is File.popen(), but that approach
makes bidirectional communications difficult.

--
Paul Lutus
http://www.ara...

Paul Lutus

9/20/2006 1:10:00 AM

0

Caio Chassot wrote:

>
> On 2006-09-19, at 21:51 , Daniel N wrote:
>
>>>
>>> You could try using IO#popen The docs are at
>>
>> http://www.ruby-doc.org/core/classes/IO.ht...
>>
>> Hope this is what your after.
>
> Looks like it. Thanks a lot.
>
> Do you know if it places the exit code in $? ?
>
> I wonder what happens if the subprocess is killed by the system?
>
> I guess I'll run some tests, but if you happen to know the answers,
> I'd be glad to hear them nonetheless.

The problem with File.popen() is that you want bidirectional communication
with the child process, and AFAIK that doesn't offer it -- you can either
read, or write, to the pipe, but not both.

--
Paul Lutus
http://www.ara...

Caio Chassot

9/20/2006 1:13:00 AM

0


On 2006-09-19, at 22:05 , Paul Lutus wrote:

> output = `echo #{s} | perl -pe "s/a/x/g"`
>
> I want to emphasize there are a dozen ways to do this. This one
> happens to
> be simple to understand. Another way is File.popen(), but that
> approach
> makes bidirectional communications difficult.

I thought about doing it with echo but then I'd have to escape the
string, and what if I was dealing with binary data, and all that...
so popen looks like a more robust solution.


Caio Chassot

9/20/2006 1:15:00 AM

0


On 2006-09-19, at 22:10 , Paul Lutus wrote:
> The problem with File.popen() is that you want bidirectional
> communication
> with the child process, and AFAIK that doesn't offer it -- you can
> either
> read, or write, to the pipe, but not both.

Hmm, that's not cool. I'll run some tests, but looks like it's back
to using tempfiles then.


Paul Lutus

9/20/2006 1:34:00 AM

0

Caio Chassot wrote:

>
> On 2006-09-19, at 22:10 , Paul Lutus wrote:
>> The problem with File.popen() is that you want bidirectional
>> communication
>> with the child process, and AFAIK that doesn't offer it -- you can
>> either
>> read, or write, to the pipe, but not both.
>
> Hmm, that's not cool. I'll run some tests, but looks like it's back
> to using tempfiles then.

Did you read my other post? Piping information to child processes is easy.

bigstring = (lots of data)

output = `echo "#{bigstring}" | child_program_name`

This has every advantage over using temp files.

--
Paul Lutus
http://www.ara...

Paul Lutus

9/20/2006 1:36:00 AM

0

Caio Chassot wrote:

>
> On 2006-09-19, at 22:05 , Paul Lutus wrote:
>
>> output = `echo #{s} | perl -pe "s/a/x/g"`
>>
>> I want to emphasize there are a dozen ways to do this. This one
>> happens to
>> be simple to understand. Another way is File.popen(), but that
>> approach
>> makes bidirectional communications difficult.
>
> I thought about doing it with echo but then I'd have to escape the
> string, and what if I was dealing with binary data, and all that...
> so popen looks like a more robust solution.

Yes, except for the fact that you cannot easily find out what the child
process created as a result. But yes, if binary data is an issue,
File.popen() will reliably stream the data for you.

--
Paul Lutus
http://www.ara...

Caio Chassot

9/20/2006 1:45:00 AM

0


On 2006-09-19, at 22:24 , Daniel N wrote:

>
> Again, I havn't used it before, but the IO#pipe command seems to
> allow for
> bi-directional control.

Yea, I figured out how to open a pipe for both read and write. You
use a numeric mode. Here's what I got:

#!/usr/bin/env ruby
io = File.popen('perl -pe s/a/b/g', 0666)
io.puts('abc')
io.close_write
puts io.read

outputs:
bbc

So it's fine for my needs. I just need to wrap it into something more
idiomatic.

Thanks Paul and Daniel