Prawn
Prawn

Reputation: 59

looking for an easy switch between "write to STDOUT" and "write to outfile"

for a program i am trying to write in perl right now, i want to build in an option that makes the output go to an output file, which is pretty easy with the perl module Getopt. however, if the option is not used, i would like the output to go to the terminal (STDOUT). for that i wrote a little script to test if i could build a switch with the module IO::File.

#!/usr/bin/env perl
use strict;
use warnings;
use Getopt::Long;
use IO::File;

my $outfilename;

GetOptions (
    "out=s" => \$outfilename,
);

my $out = IO::File->new(">$outfilename");

if (defined $out) {
    print $out "Hello World!\n";
}
else {
    print "Hello World!\n";
}

close $out if $outfilename;

although the program "runs" with or without a -o option, when i run it without -o, perl tells me that $outfilename in line 13 is not initialized, which i guess is because Getopt returns variables as "false" when the option is not used. however, i cannot think of a way to circumvent this. can you guys help me out?
also, i am absolutely sure that there is a much easier way to build in such a switch that i am not aware of. i was just writing this because i couldn't find any better way online, so if you guys have any tips on how to do that smarter, i would be very grateful!

Upvotes: 2

Views: 98

Answers (4)

ikegami
ikegami

Reputation: 385506

You get the warning because you use $outfilename as a file name unconditionally even though it only has a value when --out has been provided.

Don't put the entire print in the if. You end up with lots of duplicated code if you do that. Either create a file handle that's initialized under all conditions

my $outfh;
if (defined($outfilename)) {
   open($outfh, '>', $outfilename)
      or die($!);
} else {
   $outfh = \*STDOUT;
}

print $outfh "Hello World!\n";

or redirect STDOUT

if (defined($outfilename)) {
   open(STDOUT, '>', $outfilename)
      or die($!);
}

print "Hello World!\n";

But why aren't you redirecting STDOUT from the outside?

script >script.log

Upvotes: 4

fjardon
fjardon

Reputation: 7996

You'd better take a look at the following:

The selectcall lets you redefine what is the default file handler for the print calls. SelectSaver lets you do the same thing in the scope of a given block of code.

In your case you could rewrite your code so that you create the output file handle if needed and select it, before running the code that will do the output. The outputting code, in turn, would just call print without file handle.

Upvotes: -1

TLP
TLP

Reputation: 67900

You can use select to set the default output file handle. This will make print automatically print to the selected file handle.

if ($outfilename) {
    open my $outfh, ">", $outfilename 
       or die "Cannot open $outfilename for output: $!";
    select $outfh;
}

print "Hello world!\n";

Upvotes: 4

AKHolland
AKHolland

Reputation: 4445

You can just replace STDOUT with your filehandle, and then print normally.

if($outfilename) {
    open my $of, ">", $outfilename;
    *STDOUT = $of;
}

print "Hello World!\n";

Upvotes: 0

Related Questions