Who can propose modification to Getopt::Std which fixes the following behavior: in case you do not supply a value to the option which expect values (like "b:" below), the behavior of this module varies depending on if the parameter is the last in the line or not. If it is not the last, then the next option or argument is "eaten" as the value. Which is clearly undesirable. BTW it eats "final options separator"('--') with the same appetite as the other options.

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:

[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'};
In short test run with parameters -b -ddd
parameter_check.pl -b -ddd
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 :-)

But if the parameter without the value is the last, like in:

parameter_check.pl -ddd -b
the result is as expected: options('b') is set to zero length string.

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.


In reply to Inconsistent behavior of Getopt::Std by likbez

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.