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

I'm trying to write to a program and read it's output into a scalar. I have the writing part down fine but I don't know how to read the output. I can't use IPC::Open2 or IPC::Open3 either.

How do I capture this programs output into a scalar?
#!/usr/bin/perl -w use strict; my ( $form, $clone_from, $clone_to ) = @ARGV; # Trying to use this to capture output open( STDOUT, "|-" ) or die ("Can't open standard output: $!\n"); open( my $writeme, "| program -text -brief clone_error") or die ("Can't run write program: $!\n"); print $writeme <<EOF; $form r clone_from=$clone_from r EOF # Program works fine for write, and at this point a bunch of text is +printed from the program # to the screen. But I want to capture the output to a variable. # This was my try but it doesn't work my $output; while ( <STDOUT> ) { $output .= $_; } print "stored " . $output . " stored";

Replies are listed 'Best First'.
Re: Reading programs output into a Scalar - How?
by Joost (Canon) on Dec 15, 2006 at 20:18 UTC
    I'm a bit too tired to figure out if what you're trying to do is even possible with a piped open to self, but this:
    open( STDOUT, "|-" ) or die ("Can't open standard output: $!\n");
    Is definitely wrong: it'll fork the process and then both processes will proceed and will try to do the same thing.

    You'll want to split the task between the parent (who can write to the child) and the child (who can read from STDIN - NOT STDOUT!).

    my $pid = open( CHILD, "|-" ); unless (defined $pid) { die ("Can't open standard output: $!\n"); } if ($pid) { # in parent process (will write to CHILD) } else ($pid) { # in child process (will read from STDIN) }

    Also see perlipc.

    update:

    After some re-reading of your code, something like this will probably work too, and it's a LOT less complicated:

    my $output = `program -text -brief clone_error <<EOF $form r clone_from=$clone_from r EOF`;
    In other words, unless you really need to react to the programs output while it's running - i.e. you need to adjust the program's input based on it's output - you don't need to open a read/write pipe at all. Just supply all the input in one go and collect the output later.

Re: Reading programs output into a Scalar - How?
by jettero (Monsignor) on Dec 15, 2006 at 22:58 UTC

    I'm not sure this can be done on a system that doesn't have IPC::Open2 without knowing a lot more about the OS. It is precisely why IPC::Open2 was written afaik. For example, in linux you could use pipes to kinda fool it.

    Probably the most straight forward solution would be to open my $outputter, "|program > tmpfile", and then open the tmpfile when you're done. You know, local $/ = undef; my $entire_file = <$inputter>.

    -Paul

Re: Reading programs output into a Scalar - How?
by xorl (Deacon) on Dec 15, 2006 at 20:47 UTC
    Is this what you mean?
    [xorl@mybox]$ MYVAR = `myperlprog.pl` [xorl@mybox]$ echo $MYVAR stored output stored [xorl@mybox]$
    That's for the bash shell. Adjust as needed for other shells.

    Is this really a perl question? Even I'm not sure what exactly you're trying to do and I'm usually good at guessing what people are actually asking.

Re: Reading programs output into a Scalar - How?
by zentara (Cardinal) on Dec 16, 2006 at 13:16 UTC
    I can't use IPC::Open2 or IPC::Open3 either

    I don't know exactly what you are trying to do, but the fact that IPC::Open3 won't work, raises a flag that the program in question, may be one of those finicky one which only write to the terminal, so you now are trying to capture STDOUT. You can sometimes get around this, by running bash thru IPC and collecting it's output. Here is a simple example, you can use a more complex system for writing and reading the input output.

    #!/usr/bin/perl use warnings; use strict; use IPC::Open3; $|=1; #my $pid=open3(\*IN,\*OUT,\*ERR,'/bin/bash'); my $pid=open3(\*IN,\*OUT,0,'/bin/bash'); # set \*ERR to 0 to send STDERR to STDOUT my $cmd = 'date'; #send cmd to bash print IN "$cmd\n"; #getresult my $result = <OUT>; print $result;

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum