Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Questions about Getopt::Long 1

Status
Not open for further replies.

whn

Programmer
Oct 14, 2007
265
US
Please take a look at the piece of code below:
Code:
#!/usr/bin/perl

use strict;
use warnings;
use Getopt::Long;

my ($debug, $emailAddr, $fussy, $fussier);
GetOptions( [b]# This is line 8[/b]
  "d" => \$debug,
  "e=s" => \$emailAddr,
  "fussy" => \$fussy,
  "fussier" => \$fussier,
) || die;

if($fussy) {
  print "\$fussy = $fussy\n";
}
if($fussier) {
  print "\$fussier = $fussier\n";
}
if($debug) {
  print "\$debug = $debug\n";
}
if($emailAddr) {
  print "\$emailAddr = $emailAddr\n";
}
print "$0 exit...\n";
exit;

And some sample runs and my questions are list below in red:
Code:
% ./tt.pl -d
$debug = 1
./tt.pl exit...

% ./tt.pl -e
Option e requires an argument
Died at ./tt.pl line 8.

% ./tt.pl -e -d
$emailAddr = -d [b][COLOR=red]<-- This is a bug. How to fix it?[/color][/b]
./tt.pl exit...

% ./tt.pl -fussy
$fussy = 1
./tt.pl exit...

./tt.pl -ff
Unknown option: ff
[b]Died at ./tt.pl line 8.[/b]

% ./tt.pl -fussier
$fussier = 1
./tt.pl exit...

% ./tt.pl -fussi
$fussier = 1 [b][COLOR=red]<-- How can this happen? I'd expect to see the error: Unknown option: fussi[/color][/b]
./tt.pl exit...

Many thanks!!
 
It seems that GetOptions() does sort of wild cards expansion thing.
Code:
#!/usr/bin/perl

use strict;
use warnings; 
use Getopt::Long;

my ($ab, $ac, $xyz);
GetOptions(
  "ab" => \$ab,
  "ac" => \$ab,
  "xyz" => \$xyz,
) || die;

if($ab) {
  print "\$ab = $ab\n";
}
if($ac) {
  print "\$ac = $ac\n";
}
if($xyz) {
  print "\$xyz = $xyz\n";
}
print "$0 exit...\n";
exit;

Test runs:
Code:
% ./tt.pl -a
Option a is ambiguous (ab, ac)
Died at ./tt.pl line 8.

% ./tt.pl -x
$xyz = 1
./tt.pl exit...

Not sure if there is a way to disable GetOptions()'s wild cards expansion functionality?
 
Did you read the perdocs on Getopt::Long? There's a lot in there, but the bit below was near the top.

In the "Getting Started with Getopt::Long" section, the approximately fourth paragraph reads:
perldoc Getopt::Long said:
In the default configuration, options names may be abbreviated to uniqueness, case does not matter, and a single dash is sufficient, even for long option names. Also, options may be placed between non-option arguments. See "Configuring Getopt::Long" for more details on how to configure Getopt::Long.

The auto_abbrev option looks like it handles the specific behavior you were noticing.

 
To rharsh,

Thank you for pointing out the perldoc. I just read it:

auto_abbrev
Allow option names to be abbreviated to uniqueness. Default is enabled unless environment variable POSIXLY_CORRECT has been set, in which case auto_abbrev is disabled.

But when I set the environment in the code, I don't see the difference:

$ENV{POSIXLY_CORRECT} = 1;

Am I setting the $ENV{POSIXLY_CORRECT} correctly syntax-wise? OMG, I feel so retarded.

Code:
#!/usr/bin/perl

use strict;
use warnings;
use Getopt::Long;

[b][COLOR=red]$ENV{POSIXLY_CORRECT} = 1;[/color][/b]
my ($ab, $ac, $xyz);
GetOptions(
  "ab" => \$ab,
  "ac" => \$ab,
  "xyz" => \$xyz,
) || die;

if($ab) {
  print "\$ab = $ab\n";
}
if($ac) {
  print "\$ac = $ac\n";
}
if($xyz) {
  print "\$xyz = $xyz\n";
}
print "$0 exit...\n";
exit;

Test runs:
Code:
% ./t1.pl -a
Option a is ambiguous (ab, ac)
Died at ./t1.pl line 9.

% ./t1.pl -x
$xyz = 1
./t1.pl exit...
 
This is probably going to be easier... change
Code:
use Getopt::Long;
to this
Code:
use Getopt::Long qw(:config no_auto_abbrev);
 
Thank you, rharsh. Your solution works very well.

Now, how to solve the problem below:

Sample Code:
Code:
#!/usr/bin/perl

use strict;
use warnings;
use Getopt::Long qw(:config no_auto_abbrev);

my ($email, $debug);
GetOptions(
  "d" => \$debug,
  "e=s" => \$email,
) || die;

if($email) {
  print "\$email = $email\n";
}
if($debug) {
  print "Debug mode\n";
}
print "$0 exit...\n";
exit;

And test runs:
Code:
% ./t1.pl  -e
Option e requires an argument
Died at ./t1.pl line 8.

% ./t1.pl  -e -d
$email = -d [b]//It'd be nice to post the same error message as the above.[/b]
./t1.pl exit...

Thanks!
 
If you're just going to be using single letter switches, I'd suggest using GetOpt::Std.

If you're going to stick with GetOpt::Long, the module is working like it should. Your 'e' option requires a string as an argument, it got one: '-d'. So -d isn't being read as a switch/option, but as an argument for -e.

You'll probably need to do some error checking to make sure whatever is in $email actually looks like an email address. Admittedly, I haven't used getopt::long all that much, but the behavior, while not what you're looking for, seems reasonable. You can enter references to code blocks rather than a scalar to validate the variable that's being read -- and that could be used to validate the email address and then store it. There is information about this in the perldoc.

Also, this post on perlmonks might be helpful.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top