likbez has asked for the wisdom of the Perl Monks concerning the following question:
NOTE: During testing I discovered that this module correctly processes setting the value of an option via repetition of the option letter , like -ddd.
Here is the test program that I used:
In short test run with parameters -b -ddd[0] # cat parameter_check.pl use v5.10; use warnings; use strict 'subs'; use feature 'state'; use Getopt::Std; getopts("b:cd:",\%options); if( exists $options{'b'} ){ if( $options{'b'} ){ say "option b $options{'b'}"; }else{ say "b is zero length string or equvalent"; } }else{ say 'key b does not exist'; } say "option c:", $options{'c'}; say "option d: ", $options{'d'};
produces non-intuitive result, where -ddd is eaten by -b and becomes the value of option -b. Please note that is the next option is option without parameter, like "-b -c -ddd", then the option -c will be simply not set (it will become the value of -b), but option -ddd will be processed correctly, so such error will probably will not be detected :-)parameter_check.pl -b -ddd
But if the parameter without the value is the last, like in:
the result is as expected: options('b') is set to zero length string.parameter_check.pl -ddd -b
Here are my test runs:
[0] # perl parameter_check.pl -ddd -c -b b is zero length string or equivalent option c:1 option d: dd [0] # perl parameter_check.pl -ddd -b -c option b: -c Use of uninitialized value in say at parameter_check.pl line 18. option c: option d: dd [0] # perl parameter_check.pl -ddd -b -c option b -c Use of uninitialized value in say at parameter_check.pl line 18. option c: option d: dd [0] # perl parameter_check.pl -ddd -c -b -- option b -- option c:1 option d: dd [0] # perl parameter_check.pl -c -b -ddd option b -ddd option c:1 Use of uninitialized value in say at parameter_check.pl line 19. option d:
The main loop in this module is just 60 lines of rather compact and terse Perl. I hope that one of Perl guru here can easily find elegant solution to this problem:
sub getopts ($;$) { my ($argumentative, $hash) = @_; my (@args,$first,$rest,$exit); my $errs = 0; local $_; local @EXPORT; @args = split( / */, $argumentative ); while(@ARGV && ($_ = $ARGV[0]) =~ /^-(.)(.*)/s) { ($first,$rest) = ($1,$2); if (/^--$/) { # early exit if -- shift @ARGV; last; } my $pos = index($argumentative,$first); if ($pos >= 0) { if (defined($args[$pos+1]) and ($args[$pos+1] eq ':')) { shift(@ARGV); if ($rest eq '') { ++$errs unless @ARGV; $rest = shift(@ARGV); } if (ref $hash) { $$hash{$first} = $rest; } else { ${"opt_$first"} = $rest; push( @EXPORT, "\$opt_$first" ); } } else { if (ref $hash) { $$hash{$first} = 1; } else { ${"opt_$first"} = 1; push( @EXPORT, "\$opt_$first" ); } if ($rest eq '') { shift(@ARGV); } else { $ARGV[0] = "-$rest"; } } } else { if ($first eq '-' and $rest eq 'help') { version_mess($argumentative, 'main'); help_mess($argumentative, 'main'); try_exit(); shift(@ARGV); next; } elsif ($first eq '-' and $rest eq 'version') { version_mess($argumentative, 'main'); try_exit(); shift(@ARGV); next; } warn "Unknown option: $first\n"; ++$errs; if ($rest ne '') { $ARGV[0] = "-$rest"; } else { shift(@ARGV); } }
Thank you in advance for any help.
2020-08-16 Athanasius changed <pre> to <c> tags.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Inconsistent behavior of Getopt::Std
by haukex (Archbishop) on Aug 16, 2020 at 08:58 UTC | |
by likbez (Sexton) on Aug 16, 2020 at 18:29 UTC | |
by perlfan (Parson) on Aug 17, 2020 at 06:37 UTC | |
|
Re: Inconsistent behavior of Getopt::Std
by jeffenstein (Hermit) on Aug 16, 2020 at 08:48 UTC | |
by likbez (Sexton) on Aug 16, 2020 at 11:55 UTC | |
by AnomalousMonk (Archbishop) on Aug 16, 2020 at 14:08 UTC |