Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl, how to read argv as hash?

Tags:

perl

argv

So, I've read some guides about how to use Getopt::Long and similar libs to work with argv options, and still has no clue how to use it properly because of totally unclear (as for me) documentation and guides.

I have a script. It has next arguments: -qp, -pr, -rp, -vr, and most of them are for filenames.

Currently I have this use of Getopt::Long, which I find unsuitable because I need to check what is after option every time:

for(my $i = 0; $i < @ARGV; $i+=2){
    if ($ARGV[$i] eq "-qp"){
        unless ($ARGV[$i+1] eq "-vr" or $ARGV[$i+1] eq "-pr" or $ARGV[$i+1] eq "-rp"){
            $query_params = $ARGV[$i+1];
        }
    }
    elsif ($ARGV[$i] eq "-pr"){
        unless ($ARGV[$i+1] eq "-qp" or $ARGV[$i+1] eq "-pr" or $ARGV[$i+1] eq "-rp"){
            $params = $ARGV[$i+1];
        }
    }
    elsif ($ARGV[$i] eq "-vr"){
        unless ($ARGV[$i+1] eq "-vr" or $ARGV[$i+1] eq "-qp" or $ARGV[$i+1] eq "-rp"){
            $variables = $ARGV[$i+1];
        }
    }
    elsif ($ARGV[$i] eq "-rp"){
        unless ($ARGV[$i+1] eq "-qp" or $ARGV[$i+1] eq "-pr" or $ARGV[$i+1] eq "-vr"){
            $replace = $ARGV[$i+1];
        }
    }
} 

Maybe I don't need to use exact Getopt libs for Unix, I need just to pass some args to script. Is there any way to make it more simple and correct?

like image 522
genesi5 Avatar asked Dec 05 '25 19:12

genesi5


2 Answers

Contrary to your claims, you aren't using Getopt::Long. But you should!

use strict;
use warnings qw( all );
use feature qw( say );

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

my %opts; 

sub parse_args {
   %opts = ();
   Getopt::Long::Configure(qw( posix_default ));
   GetOptions(
      'help|h|?' => \&help,
      'qp:s' => \$opts{qp},
      'pr:s' => \$opts{pr},
      'rp:s' => \$opts{rp},
      'vr:s' => \$opts{vr},
   )
      or usage();
}

parse_args();

Using :s instead of =s makes the option's argument optional as requested in the comments.

Sample helper subs to complete the above:

sub help {
   my $prog = basename($0);
   say "usage: $prog [options]";
   say "       $prog --help";
   say "";
   say "Options:";
   say "   --qp path   ...explanation...";
   say "   --qp        ...explanation...";
   say "   --pr path   ...explanation...";
   say "   --pr        ...explanation...";
   say "   --rp path   ...explanation...";
   say "   --rp        ...explanation...";
   say "   --vr path   ...explanation...";
   say "   --vr        ...explanation...";
   exit(0);
}

sub usage {
   my $prog = basename($0);
   warn(@_) if @_;
   warn("Try `$prog --help' for more information\n");
   exit(1);
}
like image 153
ikegami Avatar answered Dec 08 '25 11:12

ikegami


A quick example from the docs of Getopt::Long.

You could now call this script with script --qp=file1 --pr=file2 --rp=file2

What Getopt:Long does for you is sort out the values given on command line to where you tell it to put them, as well as some basic validation (the =s here means you're expecting a string).

If you want to check, for example, that the given files exist, you need to do that by hand.

use strict;
use warnings;

use Getopt::Long;

my ($qp,$pr,$rp);
my $verbose;

GetOptions (
    "qp=s" => \$qp,
    "pr=s" => \$pr,
    "rp=s" => \$rp,
    "verbose" => \$verbose,
) or die "Error in command line arguments";

print "Being verbose.\n" if $verbose;

# Quick check all are there if they're all required (?)
die "qp,pr and rp are required!" if grep{ !$_ }($qp,$pr,$rp);

for my $fn ( $qp,$pr,$rp ){
    die "Cannot find file '$fn'" unless -f $fn;
}

print "you've given: qp $qp, pr $pr, rp $rp.\n";
like image 44
bytepusher Avatar answered Dec 08 '25 11:12

bytepusher