Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

Redirecting STDOUT to a variable via eval?

by mr.nick (Chaplain)
on Feb 12, 2001 at 08:40 UTC ( #57837=perlquestion: print w/replies, xml ) Need Help??

mr.nick has asked for the wisdom of the Perl Monks concerning the following question:

An interesting question, no? Would it be possible to redirect the output of an eval'd statement that contains print to a variable? I'm thinking along the lines of
my $hello='print "Goodbye System!"'; my $result=special_eval $hello; print $results; # which would print "Goodbye System"
Oh, and it can't used a file for temporary storage (yes, it would be easy enough to redirect STDOUT to a /tmp/foobar.$$ file and snarf it back in, but this approach isn't possible in the actual situation).

For background, the purpose of this is to provide a mechanism for a person to write a Perl script that behaves the same whether you are running it from a command line or having a shell-type program execute it for you.

intrigued... me

Replies are listed 'Best First'.
Re (tilly) 1: Redirecting STDOUT to a variable via eval?
by tilly (Archbishop) on Feb 12, 2001 at 08:52 UTC
    Just a quick hack, requires 5.004 or better:
    use IO::Scalar; sub var_eval { local *FH; my $fh; tie (*FH, 'IO::Scalar', \$fh); $saved = select FH; eval shift; select $saved; $fh; }
    This requires (obviously) IO::Scalar.
      Hm. This seems to act strangely. It appears that anything externally spawned from the eval's block doesn't inherit the new STDOUT (which is what the select $fh sets, correct?). For example, the following doesn't work
      $eval='system("ls")'; $result=var_eval($eval);
      I'm not overly concerned about this, but am kind of curious as to why it works this way. I can't seem to wrap my brain around "why?".
        That is because tie only is working on Perl IO. A system command hands the file descriptor for STDOUT to the command being launched, which knows nothing about Perl's IO.

        The same gotcha exists for working with C extensions that do their own printing.

        For one solution you can do a piped open like this:

        use IPC::Open3; sub piped_cmd { local *TO; local *FROM; open3 (\*TO, \*FROM, \*FROM, "perl") or die "Cannot launch perl: $!" +; print TO @_, "\n__END__\n"; local $/; <FROM>; }
        (That is portable, Windows and Unix.)

        Note that doing things that way does not give access to various things that you have defined in your script. If you want that you are probably out of luck because all of the methods that I know of for IO games (select, tie, etc) work at the Perl level, and leave the C file-descriptors alone. But then when you call system the program works by file descriptor. :-(

        This could be construed as a bug.

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (3)
As of 2022-01-19 21:04 GMT
Find Nodes?
    Voting Booth?
    In 2022, my preferred method to securely store passwords is:

    Results (56 votes). Check out past polls.