http://www.perlmonks.org?node_id=127414

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

I want to eval() a small Perl "scriptlet" and capture stdout (the script will print a few datapoints)

Being mostly a windows person, I never really got familiar with stdin/out/err...

I think eval() returns the value of the last statement...but the "script" print statements should be going to stdout...

Can I catch them? Is stdout just a never ending buffer? Can I just read it like a variable at anytime?

Thanks for any clarification on how this works

Replies are listed 'Best First'.
Re: stdout question
by Fastolfe (Vicar) on Nov 26, 2001 at 02:09 UTC
    IO::Scalar or IO::String may be what you want, to create a filehandle that represents the data in a Perl scalar. Combine that with select, which tells Perl what "default" file handle to use for things like print, and you can send data directly to the scalar as if it were a filehandle. Note that this is incompatible with things like system or exec, since select's defaults only apply to Perl code itself. You aren't really affecting STDOUT, just the "implicit" file handle Perl uses for its functions. This may be sufficient for your needs.
    use IO::String; my $buffer; my $oldfh = select(new IO::String \$buffer); eval ' print "This is a test."; ' or die; select($oldfh); print "Captured: '$buffer'\n";
Re: stdout question
by trantor (Chaplain) on Nov 26, 2001 at 02:17 UTC

    From what I understand, you want to eval a snippet of perl code in the current context (e.g. package, lexicals, etc.) and capture its STDOUT.

    Backticks do not allow you to do it, even though you can execute perl code in that way and capture STDOUT with no problems thanks to the backtick interpolation.

    If you use tie and IO::Scalar, you can actually execute a piece of perl code through eval and capture one or more of its filehandles. Basically using tie (reading perltie first) is a powerful way for achieving this and many other "fancy" results.

    This is an example of code:

    #!/usr/bin/perl -w use strict; use IO::Scalar; my $code = 'print "Hello, world!"'; my $buffer; tie *STDOUT, 'IO::Scalar', \$buffer; eval($code); untie *STDOUT; print "The captured STDOUT is: >>>$buffer<<<\n";

    Using Super Search, it is possible to find other useful threads like capturing STDOUT.

    Also note that this leads to major security issues, i.e. if your code is not carefully constructed/screened before being evalled.

    UPDATE: fastolfe came first using IO::Scalar but he's using select ;-)

    -- TMTOWTDI

(RhetTbull) Re: stdout question
by RhetTbull (Curate) on Nov 26, 2001 at 01:32 UTC
    Depending on what you're trying to do, backticks may be what you're looking for. Executing something like:
    my $stuff = `foo`;
    will capture whatever foo printed to stdout in the variable $stuff. Alternatively, you can get more complicated output filtering with Filter::Handle.
Re: stdout question
by dvergin (Monsignor) on Nov 26, 2001 at 01:33 UTC
    Backticks are your friends. This was tested on Windows:
    #!/usr/bin/perl -w # test-stdout.pl use strict; print "Hello, world."; -------------------------- #!/usr/bin/perl -w # test.pl use strict; my $prog_output = `perl test-stdout.pl`; print "\nIt said [$prog_output]\n";
    Or if you like, you can use qx( ), which does the same thing as backticks.
Re: stdout question
by hotshot (Prior) on Nov 26, 2001 at 13:01 UTC
    It depends on what you want, as somwone already said here, if you are looking for outputs from your script then the back ticks are your friends. but output from system commands is a little different especially if you want the errors returned from it. to get the error message itself you can use the back ticks but to get the error code use the system():
    $errorCode = system("SYSCOMMAND");
    you can also use $! for retrieving the error message after the execution of a command.

    Hotshot