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

My problem: Using getopt::Long , using options with both arguments and no arguments

example1: ./ldapadmin --adduser example2: ./ldapadmin --adduser Manuel,Castillo,F

(basically I want the program to know 'adduser flag is on with no arguments' or 'adduser flag called with arguments')

Both of these should work. Reading the Getopt::Long documentation, I noticed that you can set arguments as optional via : character instead of = (ex. 'adduser:s' => \@adduser) however, in example 1, the value of @adduser is false as if it has never been called!

my possible workaround: use $#ARGV and @ARGV before calling getoptions and keep track of flag this way, if $ARGV[0] contains --adduser and value of $#ARGV is 1, then it mustve been called with no arguments.

problem: Am i using getoptions incorrectly? Module documentation doesn't seem to be too informative, too short if you ask me.

here is a piece of my code---------------------------

my $argn = $#ARGV; # num of args stored in $argn my @argvee = @ARGV; # actual arguments stored in @argvee # above was done before GetOptions loads, since it seems to eat ARGV.. +. GetOptions ( 'adduser:s' => \@adduser, 'deluser=s' => \$deluser, 'addgroup=s' => \@addgroup, 'delgroup=s' => \$delgroup, 'addu2g=s' => \@addu2g, 'delu2g=s' => \@delu2g, 'chsh=s' => \@chsh, 'addalias=s' => \@addalias, 'delalias=s' => \@delalias, 'list' => \$list, 'help' => \$help ); @adduser = split(/,/,join(',',@adduser)); #take in info and split on c +ommas

thanks for your help

Replies are listed 'Best First'.
Re: using Getopt::Long, arguments and no arguments possible?
by Tanktalus (Canon) on Jul 19, 2006 at 19:54 UTC

    This is yet another reason why I like the "store options in a hash" ability:

    #!/usr/bin/perl use strict; use warnings; use Getopt::Long; my %args; GetOptions(\%args, 'adduser:s@'); use Data::Dumper; print Dumper(\%args);
    When used, this shows:
    $ perl ./a.pl $VAR1 = {}; $ perl ./a.pl --adduser $VAR1 = { 'adduser' => [ '' ] }; $ perl ./a.pl --adduser blah $VAR1 = { 'adduser' => [ 'blah' ] };
    So, if the option isn't specified, it doesn't end up as a key in the hash. If the option is specified, but without any parameter, the key shows up, but the value is an array reference containing an empty string. If the option is specified with a parameter, then the key is there, pointing to an array containing the parameter. Note that --adduser and --adduser "" both do the same thing. Which is probably fine.

Re: using Getopt::Long, arguments and no arguments possible?
by ikegami (Patriarch) on Jul 19, 2006 at 19:50 UTC
    Works fine for me. (Getopt::Long v2.25)
    does @adduser = () --adduser does @adduser = ('') --adduser Joe does @adduser = ('Joe') --adduser Joe --adduser Frank does @adduser = ('Joe', 'Frank') --adduser --adduser Joe does @adduser = ('', 'Joe')

    It even works find with your join-split (which would be better written as @adduser = map { split /,/ } @adduser;).

Re: using Getopt::Long, arguments and no arguments possible?
by bobf (Monsignor) on Jul 19, 2006 at 22:07 UTC

    ikegami and Tanktalus have already shown you examples of better ways to do it, but in the spirit of TIMTOWTDI here are a couple other (ab)uses of the Getopt::Long features. The first takes advantage of the ability to assign a user-defined subroutine to an option to use during processing (which I use to set a flag and then store the value of the option). The second creates a copy of the original command line before it is processed and simply uses a regex to determine if a given option was present (without attempting to retrieve the value). I used a combination of single- and double-dashes to show it works both ways.

    use strict; use warnings; use Getopt::Long; # make a copy of the cmd line before GetOptions processes it my $cmd_line = join( ' ', @ARGV ); my $saw_something = 0; my @things; GetOptions( 'something:s' => sub { shift @_; $saw_something = 1; push( @things, grep { $_ ne '' } @_ + ); } ); if( $cmd_line =~ m/-?-something\b/ ) { print "I saw something on the cmd line\n"; } if( $saw_something ) { if( scalar @things ) { print 'And it was ' . join( ' ', @things ) . "\n"; } else { print "But I don't know what I saw\n"; } }

    For example:

    C:\>test.pl --something NodeReaper I saw something on the cmd line And it was NodeReaper
    There are times, however, when we know we saw something but we don't want to know what it was:
    C:\>test.pl --something I saw something on the cmd line But I don't know what I saw
    This works for multiple values, too:
    C:\>test.pl --something a -something grue I saw something on the cmd line And it was a grue