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

My question is quite simple, but unfortunately I can't resolve it:

I'd like to use a command line option with- or without an argument as a flag:

if it has an argument then the value of my scalar should be the argument, otherwise its value should be the default value. The command line may contain other arguments and I'd like to keep the @ARGV untouched.

I've started to play with the Getopt::Long modul and felt myself very close to the solution, but unfortunately it wasn't perfect:

use Getopt::Long; #my $foo = 1; GetOptions ('foo=s', \$foo); print "foo: $foo\n" if $foo; print "Unprocessed by Getopt::Long\n" if $ARGV[0]; foreach (@ARGV) { print "$_\n"; }

eg.:
>perl test.pl something -foo "my argument"
works fine, but
>perl test.pl something -foo
results a message: "Option foo requires an argument", even if you added a default value for your option in the code (see the commented line). (The GetOptions ('foo:s', \$foo) with the : type) doesn't drop error message, but the $foo has no value at all.) What I wanna reach is $foo with the default value (without error message) or $foo with the value if there is a value for -foo. Of course I no need the default value if there isn't the -foo argument in the command line at all.

I found a quite similar problem in between the recent nodes: Requiring option values in Getopt::Long, but there is no solution for my problem...

Thanks in advance

Replies are listed 'Best First'.
Re: command line option with- or without argument
by james2vegas (Chaplain) on Aug 29, 2009 at 13:45 UTC
    From Getopt::Long:
    Using a colon ":" instead of the equals sign indicates that the option value is optional. In this case, if no suitable value is supplied, string valued options get an empty string '' assigned, while + numeric options are set to 0.

    Update: Something like
    use strict; use warnings; use Getopt::Long; my $foo; GetOptions ('foo:s', \$foo); print "foo: $foo\n" if defined($foo); print "Unprocessed by Getopt::Long\n" if $ARGV[0]; foreach (@ARGV) { print "$_\n"; }

    Note that you should check for definedness rather than truth in $foo as the default values for optional parameters (0 and '') are false values.

      Dear james2vegas,

      Thanks a lot! i wouldn't thought that the keyword is so simple: "if defined($foo)"

      With the best

Re: command line option with- or without argument
by toolic (Bishop) on Aug 29, 2009 at 14:28 UTC
    Building upon james2vegas's solution and explanation, and satisfying all of your stated requirements:
    • If -foo is not on the command line, leave $foo undefined.
    • If -foo is on the command line without an argument, set $foo to a default value of 1, without the error message.
    • If -foo is on the command line with an argument, set $foo to the argument.
    use strict; use warnings; use Getopt::Long; my $foo; GetOptions ('foo:s', \$foo); if (defined $foo) { $foo = 1 if $foo eq ''; print "foo: $foo\n"; } print "Unprocessed by Getopt::Long\n" if $ARGV[0]; foreach (@ARGV) { print "arg=$_\n"; }