Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Merging two pipes

by cmburns (Acolyte)
on Oct 24, 2001 at 12:43 UTC ( [id://121027]=perlquestion: print w/replies, xml ) Need Help??

cmburns has asked for the wisdom of the Perl Monks concerning the following question:

Hi there!

I have some trouble understanding how to redirect input from one pipe to another. Here is what I want to do:

I open one command and process its output in a while loop. On some condition I open another command inside this while loop and I want its output to appear in the same pipe as the output of the first command.

Ok, here's some pseudo-code to make things a bit more clear:

open INPUT, "some_script |"; while (<INPUT>) { if ($some_condition) { open ">&INPUT", "some_other_script |"; } do_something_with_input(); }

(I know there are missing close and or die statements.) Both scripts run over some period of time and give progress information (like 50% done) as their output, so it's important to monitor output from both scripts simultaneously.

Any ideas? Is this possible?

Thanks alot for your help!

Replies are listed 'Best First'.
Re: Merging two pipes
by tommyw (Hermit) on Oct 24, 2001 at 14:00 UTC

    Oh well, if we're all having a go...

    You need to monitor some script, and at certain points start other scripts, and monitor those too?

    open HANDLE, "some_script |"; push @INPUT, *HANDLE; while (<@INPUT>) { if ($some_condition) { open HANDLE, "some_other_script |"; push @INPUT, *HANDLE; } do_something_with_input(); }
    Where <@INPUT> is pseudo-code for reading from one of the files in @INPUT, without blocking.

    The perl cookbook suggests:

    use IO::Select; $select = IO::Select->new(); # repeat next line for all filehandles to poll $select->add(*FILEHANDLE); if (@ready = $select->can_read(0)) { # input waiting on the filehandles in @ready }
    to perform this check. Putting the two together is left as an excercise for the reader.

Re: Merging two pipes
by Zaxo (Archbishop) on Oct 24, 2001 at 13:52 UTC

    When you reopen INPUT (the '>&' symbols are an error) the original is closed. You need to open two distinct filehandles and use four argument select ('perldoc -f select') to read them simultaneously.

    It is educational to roll your own select loop, but IO::Select is the way to get it done. 'man IO::Select' will tell you if you already have it, and how to use it.

    After Compline,
    Zaxo

      Thanks to all of you!

      I must admit I didn't make my problem quite clear but your comments put me on the right trail. IO::Select did the trick for me and now my script works like I want it to.

Re: Merging two pipes
by jeroenes (Priest) on Oct 24, 2001 at 13:36 UTC
    Your pseudo-code and your words tell me two different stories. First your pseudo-code (and without the die's):
    open INPUT from some_script; read input if some_condition open >&INPUT from some_other_script do_something

    While you say that you want INPUT from one script, and output from two scripts to one pipe. That means:

    open INPUT, "some_script |"; open OUTPUT, "| some_other_other_script "; while (<INPUT>){ if ($some_condition){ open INPUT2, "some_other_script |"; print OUTPUT $_ while <INPUT2>; } print OUTPUT $_; }

    Whatever the case, think of the two forms of pipe (input/output) and realize that ">&INPUT" is just an illegal name for a GLOB.

    HTH,

    Jeroen
    "We are not alone"(FZ)

Re: Merging two pipes
by jj808 (Hermit) on Oct 24, 2001 at 13:34 UTC
    Try opening pipes from both scripts at the start of your program, then make INPUT a duplicate of these filehandles, e.g.
    open SCRIPT, "some_script |"; open OTHERSCRIPT, "some_other_script |"; open INPUT, ">&SCRIPT"; while (<INPUT>) { if ($some_condition) { close (INPUT); open INPUT,">&OTHERSCRIPT"; } do_something_with_input(); if ($some_other_condition) { close (INPUT); open INPUT,">&SCRIPT"; } }
    Again the die statements have been left out - I'm sure you will want to put them in for production code.

    I've not tested the above code, but looking at the open documentation this should be what you need.

    Cheers,

    JJ

    Update: I've just read jeroenes reply, and I think that I may have misunderstood your question. Do you need both your inputs on the same filehandle?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://121027]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (3)
As of 2024-04-25 04:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found