karlberry has asked for the wisdom of the Perl Monks concerning the following question:

I find myself surprised that Getopt::Long apaprently prefers the last case-insensitive match of an option name. Specifically:
#!/usr/bin/env perl use strict; use warnings; use Getopt::Long; #use Getopt::Long qw(:config no_ignore_case); my $opt_verbose = 0; my $opt_version = 0; GetOptions( "verbose|v" => \$opt_verbose, "version|V" => \$opt_version, ) or die "getopt failed"; print "verbose=$opt_verbose, version=$opt_version\n";
If I save this as try.pl and run try.pl -v, the result is verbose=0, version=1.

I would have expected either for the exact case match to be preferred, or getopt to complain, per its documentation:

With "ignore_case", option specifications for options that only differ in case, e.g., "foo" and "Foo", will be flagged as duplicates.
but apparently this does not happen for alternate names.

Workarounds are possible, such as the commented-out :config no_ignore_case, or switching the order of the option specifications. But it feels wrong that the result depends on the order given.

I don't expect the behavior to change after all these years, but maybe there is something to say in the doc. Or am I missing something already there that explains the behavior? It seems like this (v vs. V) would be such a common case that I doubt I'm discovering anything new here.

I tried with perl 5.36.1, also 5.24.0 (just an old version I had at hand), and (as expected) results were the same.

Thanks for any wisdom ... --karl

Replies are listed 'Best First'.
Re: Getopt::Long case matching last wins
by hippo (Archbishop) on May 28, 2023 at 15:21 UTC
    Workarounds are possible, such as the commented-out :config no_ignore_case

    no_ignore_case is not what I would consider a work-around. It's a feature intentionally provided by the module author for users who want case-sensitivity throughout. It seems to be precisely the solution to the problem you have encountered - why not use it?


    🦛

      I'm asking why getopt does not complain about the case ambiguity (of v/V), as it is documented to do, instead of arbitrarily picking the last one. Or, perhaps I'm asking if it's a bug (either documentation or code) or if I'm missing something.

        Interestingly it does flag the aliases for me:

        $ perl -MGetopt::Long -we 'GetOptions ("a|x" => \$x, "A|y" => \$y);' Name "main::y" used only once: possible typo at -e line 1. Name "main::x" used only once: possible typo at -e line 1. Duplicate specification "A|y" for option "a" $ perl -MGetopt::Long -we 'GetOptions ("a|x" => \$x, "b|X" => \$y);' Name "main::y" used only once: possible typo at -e line 1. Name "main::x" used only once: possible typo at -e line 1. Duplicate specification "b|X" for option "x"

        So if either the primary or the alias is non-unique in a case-insensitive way, the warning is shown. I'm using version 2.52 of Getopt::Long.


        🦛

Re: Getopt::Long case matching last wins
by sciurius (Beadle) on Jun 01, 2023 at 06:45 UTC
    > I would have expected either for the exact case match to be preferred, or getopt to complain, per its documentation

    I'm not sure why this warning is suppressed unless $^W. I'll change the behaviour to die in this case. It's a programmer (caller) error.