Arthes
Arthes

Reputation: 79

How do I redirect eval output to a file?

I am writing a Perl script where I read files containing section Perl code and non Perl data.

After processing the files I write them to a temporary files (generated scripts) which is then executed using an eval command. I don't want to run the generated script separately as I need to use the variables in the main script to be interpolated in the generated scripts.

I need to redirect the output of the eval command to a file. Any suggestion on how to achieve this?

Steps in the script:

  1. READ_FILE

  2. Process file

  3. Write back with temp file name

  4. Read temp file (my $file_name = read_file('temp_file_name'))

  5. eval (eval $file_name)

Appreciate the help.

Upvotes: 2

Views: 1516

Answers (3)

HoldOffHunger
HoldOffHunger

Reputation: 20851

TLDR Answer

use Capture::Tiny; with capture_merged() or capture(). You may use capture_stdout() if you like it as a shortcut.

Output? Which output stream? STDOUT or STDERR?

According to Perl, output can be in the form of:

  • STDOUT — Typically caused by print(), etc., statements.
  • STDERR — Typically caused by warn(), etc., statements.

You can use Capture::Tiny to get STDOUT and STDERR merged:

my ($merged,  @result) = capture_merged { eval $codetoeval };

Or, you can use Capture:Tiny to get them separated:

my ($stdout, $stderr, @result) = capture { eval $codetoeval };

You also have the option of capture_stdout() and capture_stderr() if you only want those forms of output. If you only have print() statements, then capture() and capture_stdout() will give the same results.

Complete Demo

use Capture::Tiny ':all';
my $codetoeval = 'print "Hello, World!";';
my ($merged,  @result) = capture_merged { eval $codetoeval };
die "Merge Fail" if !@result;
print("Output : " . $merged);
open my $fh, '>', 'foo.txt' or die $!;
print $fh $stdout;

Full Working Online Demo at IDEOne

Output: Hello, World!

Upvotes: 0

Borodin
Borodin

Reputation: 126722

This can be done without any additional modules

use strict;
use warnings;

open my $fh, '>', 'foo.txt' or die $!;
my $old_fh = select $fh;

eval q{ print "Hello World!\n"; };

select $old_fh;

Upvotes: 6

simbabque
simbabque

Reputation: 54323

You can use capture_stdout from Capture::Tiny to grab the output of your eval.

use strict;
use warnings;
use Capture::Tiny 'capture_stdout';

my $stdout = capture_stdout {
    eval q{print "Hello World!\n";};
};

open my $fh, '>', 'foo.txt' or die $!;
print $fh $stdout;

Upvotes: 7

Related Questions