Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Redirecting STDOUT to a variable via eval?

by mr.nick (Chaplain)
on Feb 12, 2001 at 08:40 UTC ( [id://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; }
    UPDATE
    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?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (4)
As of 2024-04-19 05:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found