Search code examples
perlgetopt

Handle repeated options like -v -vv -vvv idiomatically with perl Getopt


I'd like to handle the verbosity level option like OpenSSH does: by multiply passing the -v option.

Getopt::Std does not increment no-argument option values, but simply sets them to 1. This means that passing -vvv with Getopt::Std will yield $opt_v == 1 and I need it to be 3 in that case.

Getopt::Long with the v+ option-spec understands -v -v correctly (target variable ends up 2), but it misunderstands -vvv as the option named vvv -- which is not defined and causes an error.

How can I get the desired behavior?


Solution

  • I figured out the answer after writing up the question, but before posting it -- classic.


    The best way to handle this is to use Getopt::Long with bundling:

    use Getopt::Long qw(:config bundling);
    GetOptions ("v+" => \$verbose);
    

    This handles -v -vv -vvv as expected: $verbose == 6.


    If for some reason you cannot use or prefer not to use bundling, the only other way is to define the options vv, vvv etc. up to a reasonable maximum:

    use Getopt::Long;
    GetOptions (
        "v+" => \$verbose);
        "vv" => sub { $verbose += 2 },
        "vvv" => sub { $verbose += 3 },
    );
    

    This then also handles -v -vv -vvv as expected: $verbose == 6.