Home > database >  How can I check the number of command line argument passed in Perl?
How can I check the number of command line argument passed in Perl?

Time:03-24

I have a script that runs in the following way:

perl testing.pl -grid 24 -range 97   ## Here, arguments passed are processed via getopt::Long module.

Now, I want to check the number of command-line arguments passed to the script. Expected is 2. But I am getting 0.

I used below piece of code inside the script (testing.pl) to extract the number of arguments:

my $totalCmdLineArg = $#ARGV   1;
print "$totalCmdLineArg is total command line arguments\n";
if ($totalCmdLineArg <= 0 ) {
    $defaultmode=1;
} else {
    $defaultmode=0;
}

Here, I am getting "0 is total command line arguments" as output. I would want "2 is total command line arguments" as output. How can I get the expected answer?

Note: There are 100 arguments out of which any can be passed.

CodePudding user response:

You can't count options after GetOptions has been called. GetOptions removes the options it recognizes from @ARGV. Quoting its documentation:

The command line options are taken from array @ARGV. Upon completion of GetOptions, @ARGV will contain the rest (i.e. the non-options) of the command line.

Furthermore, GetOptions does not count how many options it parses. Check out the source if you need convincing.

So, if you want to count how many options were passed to your program, you have to do it manually, before calling GetOptions.

If all of the arguments on your command line have the form --option xxx, then you can simply do (before calling GetOptions):

my $totalCmdLineArg = grep { /^--/ } @ARGV

However, this ignores the fact that -- on itself in @ARGV marks the end of the option list. If your command line is something like perl prog.pl --opt1 v1 --opt2 v2 -- some additional --arguments then -- and --arguments are actually not options (for GetOptions). To handle this case, you'd have to write something like:

my $totalCmdLineArg = 0;
for (@ARGV) {
    last if $_ eq '--';
    $totalCmdLineArg   if /^--/;
}

However, this does not account for the fact that a single - can be used to start an option, and that this can be used to combine multiple options (is $Getopt::Long::bundling is non-zero). You'll have to adapt the code above to handle this case.


Only in last resort (do not used in production, might break at any time):
If you are using bundling and other complex features of Getopt::Long, you could hack a bit to count how many options Getopt::Long actually finds. Internally, GetOptions calls FindOption to actually find options. You could redefine it to count how many options are found:

my $opt_count = 0;
{
  no warnings qw(redefine prototype);
  my $original_FindOption = \&Getopt::Long::FindOption;
  *Getopt::Long::FindOption = sub {
    my @ret = &$original_FindOption;
    if ($ret[0] && defined $ret[1]) {
      $opt_count  ;
    }
    return @ret;
  };
}

Note that this is a very fragile approach: FindOption is not part of the exposed API of Getopt::Long, and could thus change between versions, which could break this code.

CodePudding user response:

There are four arguments. Two is the number of options.

If you use GetOptions to build a hash, it's simply a question of counting the number of elements in the hash.

GetOptions( \my %opts, ... )
   or usage();

my $num_options = keys( %opts );
  • Related