views:

53

answers:

5

myscript.pl

my $R;
my $f1 = "f1.log";
my $f2 = "f2.log";
my $f3 = "f3.log";

sub checkflags {

    GetOptions('a=s'    => \$f1,
               'b=s'    => \$f2,
               'c=s'    => \$f3,
    );

    open $R, '>', $f1 or die "Cannot open file\n"; # Line a
}
  • All the flags are optional.

  • If I call the script as

    perl myscript.pl -a=filename
    

    I need to append a .log to the filename before opening it at Line a.

  • For that I need to know whether GetOptions read something into $f1 or not.

How can this be done?

+1  A: 
if (defined $f1) {
  # You got a -a option
}

But personally I'd prefer to read the options into a hash and then use exists().

davorg
@davorg: that will always be true because of the initialization that I have at Line 2.
Lazer
+2  A: 

The simplest solution is to look for /[.]log$/ in $f1 and add it if it isn't present. Unfortunately that means that when the user passes in "foo.log" and wanted it to become "foo.log.log" it won't, but I think we can agree that user is a jerk.

A better option, that will make the jerk happy, is:

#!/usr/bin/perl

use strict;
use warnings;

use Getopt::Long;

GetOptions(
    'a=s'    => \my $f1,
    'b=s'    => \my $f2,
    'c=s'    => \my $f3,
);

if (defined $f1) {
    $f1 .= ".log";
} else {
    $f1 = "f1.log";
}

print "$f1\n";

If you want to define all of default names at the top, use a different variable to do that (it is probably better reading code anyway):

#!/usr/bin/perl

use strict;
use warnings;

use Getopt::Long;

my $default_f1 = "f1.log";
my $default_f2 = "f2.log";
my $default_f3 = "f3.log";

GetOptions(
    'a=s'    => \my $f1,
    'b=s'    => \my $f2,
    'c=s'    => \my $f3,
);

if (defined $f1) {
    $f1 .= ".log";
} else {
    $f1 = $default_f1;
}

print "$f1\n";
Chas. Owens
@Chas: Is there no way to check whether the flag was read or not?
Lazer
@Lazer See my edit, there is if you don't set it beforehand.
Chas. Owens
They could always just pass `foo.log.log` if they *really* wanted that filename.
ar
+1  A: 
$f1 = "$f1.log" unless $f1 =~ m/\.log$/i;

Appends the log extension if the file name does not already have one. Since the default value ends in log, nothing happens. And it works if the user types the log on the command line.

Robert Wohlfarth
@Robert: Can you please elaborate how the append using `m/\.log$/i` happens?
Lazer
What about the user who wants the log to be named `foo.log.log`?
Chas. Owens
The append happens in the assignment: $f1 = "$f1.log".
Robert Wohlfarth
A: 

It's easier if you store your defaults and options in hashes:

use strict;
use warnings;
use Getopt::Long;

my %DEFAULTS = (
    a => 'f1.log',
    b => 'f2.log',
    c => 'f3.log',
    v => 0,
);

GetOptions(\my %opt, 'a=s', 'b=s', 'c=s', 'v');
%opt = (%DEFAULTS, %opt);

$opt{$_} =~ s/(\.log)?$/.log/ for qw(a b c);
FM
A: 

One way to achieve this is to use Moose and MooseX::Getopt:

package MyApp;

use strict;
use warnings;

use Moose;
with 'MooseX::Getopt';

has f1 => (
    is => 'ro', isa => 'Str',
    cmd_aliases => 'a',
    default => 'f1.log',
    predicate => 'has_a',
);
has f2 => (
    is => 'ro', isa => 'Str',
    cmd_aliases => 'b',
    default => 'f2.log',
    predicate => 'has_b',
);
has f3 => (
    is => 'ro', isa => 'Str',
    cmd_aliases => 'c',
    default => 'f3.log',
    predicate => 'has_c',
);

# this is run immediately after construction
sub BUILD
{
    my $this = shift;

    print "a was provided\n" if $this->has_a;
    print "b was provided\n" if $this->has_b;
    print "c was provided\n" if $this->has_c;
}

1;
Ether