Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

Redirecting STDOUT

by tame1 (Pilgrim)
on Jun 14, 2002 at 13:30 UTC ( #174507=perlquestion: print w/replies, xml ) Need Help??
tame1 has asked for the wisdom of the Perl Monks concerning the following question:

I find myself in need of a way of redirecting/capturing STDOUT, but from within and program instead of from the command line.

In detail, here is the problem. We use a home grown templating system in which the template holds some perl and lots of html, with a bunch of $href->{somekey} entries.
That template is slurped up, and then eval'ed (with $href having been created/filled before the slurp and eval).

The slurped template can be edited by non-programmers, so for safety we 'use Safe'. Here is the code so far:
my $code; my $compartment = new Safe; $compartment->share('$href'); $code = $compartment->reval($$file); if ($@) { _sAbort( $r, "Restricted eval failed! Unable to compile format of +type $type:", $@ ); return DONE; }
The real problem now comes up. ANY use/call of $code->($href) will activate the print statements inside the slurped file. This was fine with the following:
$r->send_http_header('text/html'); $code->($href); return DONE;
But now I am trying to instead grab the output of $code and stick it as text into an email. (You guessed it - I'm trying to email generated web pages - HTML email, yuck!).

Surfing through the various books, I find no simple way to redirect STDOUT to a variable for capture. The following code failed miserably:
my $open_err; my $data; open(OUTPUT, "$code->($href) |") or $open_err = $!; if ($open_err) { _sAbort($r,"Cannot open a pipe",$!); return DONE; } local $/ = undef; $data = <OUTPUT>; close(OUTPUT);
Any of you geniouses know offhand how I can get this darned HTML output from the code ref $code into a simple variable so i can give it to MIME::Lite as data? Much gracious bowing and licking of boots are offered to the one who can solve this for me!

What does this little button do . .<Click>; "USER HAS SIGNED OFF FOR THE DAY"

Replies are listed 'Best First'.
Re: Redirecting STDOUT
by SarahM (Monk) on Jun 14, 2002 at 13:54 UTC
    Here is a trick I've used before. I know it works on windows...but I haven't tried it on unix. You'll need to download IO::Scalar, it comes with IO-stringy.
    use IO::Scalar; my $output; tie (*STDOUT, 'IO::Scalar', \$output); # Use this to capture STDOUT print "testout\n"; untie *STDOUT; # Use this to return STDOUT to normal print "my output='$output'";
    I hope this works for you.
      I never thought of tieing the variable... this is how I use IO::Scalar when I wish to redirect output.
      It's actually more useful for when you just need to have output to a variable rather than to some file handle:

      use IO::Scalar; my ( $STD1 $STD2 ); $STD1 = new IO::Scalar \$STD2; select $STD1; print <<DONE; blah blah blah All this is being appended to the $STD2 variable So some more text here and we are... DONE open FILE, ">test.txt"; print FILE $STD2; close FILE;
      Yes, odd example since you could have just used:

      open FILE, ">test.txt"; select FILE; print <<DONE; all that stuff again. I am DONE

      But you get the point...

Re: Redirecting STDOUT
by Abigail-II (Bishop) on Jun 14, 2002 at 14:44 UTC
    If you are on a Unix like system, you can use open my $fh => "|-" and open my $fh => "-|" as described in perlipc. Also very useful for post processing output (or preprocessing input) without changing your existing program.


Re: Redirecting STDOUT
by Dog and Pony (Priest) on Jun 14, 2002 at 13:50 UTC
    I am not sure if this will help you, but you can find several (mine and some others) takes on capturing STDOUT at STDOUT::Capture - manipulate STDOUT.
    You have moved into a dark place.
    It is pitch black. You are likely to be eaten by a grue.
(RhetTbull) Re: Redirecting STDOUT
by RhetTbull (Curate) on Jun 14, 2002 at 16:56 UTC
    This question comes up a lot... I know I've answered it at least eight times. As always, my recommended solution is to use Filter::Handle. It does a great job, requires minimum changes to existing code, and works with file handles other than STDOUT/STDERR.
      And, as pointed out in its documentation, there are things it cannot catch. The most common of which are system calls.
Re: Redirecting STDOUT
by Anonymous Monk on Jun 14, 2002 at 14:21 UTC
    I know how to redirect STDOUT to a file

    open (STDOUT, ">>myfile.log");
    Works just fine for STDERR also!

    To redirect into a variable, perhaps you can try

    @LINES = <STDOUT>;
Re: Redirecting STDOUT
by BUU (Prior) on Jun 15, 2002 at 18:43 UTC
    Is it to late to point out that there are tons of very nice templating engines already available, from html::template to ePerl? For a quick overview, you can look at "", which describes many of the common engines out there.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://174507]
Front-paged by Steve_p
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (7)
As of 2017-06-27 06:20 GMT
Find Nodes?
    Voting Booth?
    How many monitors do you use while coding?

    Results (600 votes). Check out past polls.