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 );