user1987607
user1987607

Reputation: 2157

perl - use command-line argument multiple times

I'm modifying a perl script in which the command line arguments are parsed like this:

if ($arg eq "-var1") {
    $main::variable1 = shift(@arguments)
} elsif ($arg eq "-var2") {
    $main::variable2 = shift(@arguments)
} elsif ($arg eq "var3") {
    $main::variable3 = shift(@arguments)
} ... 

So there is a whole bunch of elsif statements to cover all command-line arguments.

I'm now in a situaton where I want to use the argument '-var2' multiple times.

So my main::variable2 should maybe be an array that contains all values that are passed with "-var2".

I found that with Perl::getopt, this can be easily achieved (Perl Getopt Using Same Option Multiple Times).

However the way that my script parses its command-line arguments is different. So I was wondering if it could be achieved, without having to change the way the arguments are parsed.

Upvotes: 1

Views: 617

Answers (3)

Polar Bear
Polar Bear

Reputation: 6798

Well, it is good practice to document your core -- you would appreciate it as soon as you return to make changes

NOTE: in Linux it requires perl-doc package to be installed to use --man option in full extent

#!/usr/bin/perl
#
# Description:
#   Describe purpose of the program
#
# Parameters:
#   Describe parameters purpose
#
# Date: Tue Nov 29 1:18:00 UTC 2019
#

use warnings;
use strict;

use Getopt::Long qw(GetOptions);
use Pod::Usage;

my %opt;

GetOptions(
        'input|i=s'     => \$opt{input},
        'output|o=s'    => \$opt{output},
        'debug|d'       => \$opt{debug},
        'help|?'        => \$opt{help},
        'man'           => \$opt{man}
) or pod2usage(2);

pod2usage(1) if $opt{help};
pod2usage(-exitval => 0, -verbose => 2) if $opt{man};

print Dumper(\%opt) if $opt{debug};


__END__

=head1 NAME

program - describe program's functionality 

=head1 SYNOPSIS

program.pl [options]

 Options:
    -i,--input  input filename
    -o,--output output filename
    -d,--debug  output debug information
    -?,--help   brief help message
       --man    full documentation

=head1 OPTIONS

=over 4

=item B<-i,--input>

Input filename

=item B<-o,--output>

Output filename

=item B<-d,--debug>

Print debug information.

=item B<-?,--help>

Print a brief help message and exits.

=item B<--man>

Prints the manual page and exits.

=back

B<This program> accepts B<several parameters> and operates with B<them> to produce some B<result>

=cut

Upvotes: 1

ikegami
ikegami

Reputation: 385506

This particular wheel already exists. Please don't try to reinvent it. That just makes it a pain for the people trying to use your script. There's no reason to force people to learn a whole new set of rules in order to execute your program.

use File::Basename qw( basename );
use Getopt::Long   qw( );

my $foo;
my @bars;
my $baz;

sub help {
   my $prog = basename($0);
   print
"Usage:
  $prog [options]
  $prog --help

Options:
  --foo foo
      ...

  --bar bar
      May be used multiple times.
      ...

  --baz baz
      ...
";
   exit(0);
}


sub usage {
   if (@_) {
      my ($msg) = @_;
      chomp($msg);
      say STDERR $msg;
   }

   my $prog = basename($0);
   say STDERR "Try '$prog --help' for more information.";
   exit(1);
}


sub parse_args {
   Getopt::Long::Configure(qw( posix_default ));
   Getopt::Long::GetOptions(
      "help"  => \&help,
      "foo=s" => \$foo,
      "bar=s" => \@bars,
      "baz=s" => \$baz,
   )
      or usage();

   !@ARGV
      or usage("Too many arguments");

   return @ARGV;
}


main(parse_args());

Upvotes: 3

Dave Cross
Dave Cross

Reputation: 69224

That's not your actual code, is it? It won't even compile.

I'd be really surprised if Getopt::Long can't solve your problem and it's really a better idea to use a library rather than writing your own code.

But changing your code to store -var2 options in an array is simple enough.

my ($variable1, @variable2, $variable3);

if ($arg eq "-var1") {
    $variable1 = shift(@arguments)
} elsif ($arg eq "-var2") {
    push @variable2, shift(@arguments)
} elsif ($arg eq "-var3") {
    $variable3 = shift(@arguments)
}

(I've also removed the main:: from your variables and added the, presumably missing, $s. It's really unlikely that you want to be using package variables rather than lexical variables.)

Upvotes: 4

Related Questions