views:

182

answers:

3

If I have a command line like:

my_script.pl -foo -WHATEVER

My script knows about --foo, and I want Getopt to set variable $opt_foo, but I don't know anything about -WHATEVER. How can I tell Getopt to parse out the options that I've told it about, and then get the rest of the arguments in a string variable or a list.

An example:

use strict;
use warnings;

use Getopt::Long;

my $foo; 

GetOptions('foo' => \$foo); 

print 'remaining options: ', @ARGV;

Then, issuing

perl getopttest.pl -foo -WHATEVER

gives

Unknown option: whatever
remaining options:
+1  A: 

Aren't the remaining (unparsed) values simply left behind in @ARGV? If your extra content starts with dashes, you will need to indicate the end of the options list with a --:

#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use Data::Dumper;

my $foo;
my $result = GetOptions ("foo"   => \$foo);
print Dumper([ $foo, \@ARGV ]);

Then calling:

my_script.pl --foo -- --WHATEVER

gives:

$VAR1 = [
          1,
          [
            '--WHATEVER'
          ]
        ];

PS. In MooseX::Getopt, the "remaining" options from the command line are put into the extra_argv attribute as an arrayref -- so I'd recommend converting!

Ether
They aren't if they look like options. Instead, an error like `Unknown option: WHATEVER` will be issued to STDERR.
Robert P
@Robert: your comment and my edit crossed in the ether :)
Ether
:] Indeed! Haha, I added an example like that to the question, too.
Robert P
A: 

I think the answer here, sadly though, is "no, there isn't a way to do it exactly like you ask, using Getopt::Long, without parsing @ARGV on your own." Ether has a decent workaround, though. It's a feature as far as most people are concerned that any option-like argument is captured as an error. Normally, you can do

GetOptions('foo' => \$foo) 
    or die "Whups, got options we don't recognize!";

to capture/prevent odd options from being passed, and then you can correct the user on usage. Alternatively, you can simply pass through and ignore them.

Robert P
+7  A: 

You need to configure "pass_through" option via Getopt::Long::Configure("pass_through");

Then it support actual options (e.g. stuff starting with "-" and without the special "--" delimiter to signify the end of "real" options).

Here's perldoc quote:

  • pass_through (default: disabled)

    Options that are unknown, ambiguous or supplied with an invalid option value are passed through in @ARGV instead of being flagged as errors. This makes it possible to write wrapper scripts that process only part of the user supplied command line arguments, and pass the remaining options to some other program.

Here's an example

$ cat my_script.pl
#!/usr/local/bin/perl5.8 -w

use Getopt::Long;
Getopt::Long::Configure("pass_through");
use Data::Dumper;
my %args;
GetOptions(\%args, "foo") or die "GetOption returned 0\n";
print Data::Dumper->Dump([\@ARGV],["ARGV"]);

$ ./my_script.pl -foo -WHATEVER          
$ARGV = [
          '-WHATEVER'
        ];
DVK
A ha, that would explain why I didn't find it... :)
Ether
I find it absolutely infuriating reading about some neat option on perldoc website and then go back to my mesosoic corporate Perl installation and find that the exact perfect option I've found requires a flux capacitor, or at least a CPAN module upgrade
DVK
@DVK : Are you sure `pass_through` isn't available with 5.8? I just checked `perldoc Getopt::Long` for 5.6.1 (and you thought you were pre-historic ;)) and it's there.
Zaid
@Zaid - you're absolutely right! I didn't quite read the POD right and was looking for an option configured through `import`; and this one is done via special `Configure()` call. I have updated my answer.
DVK
I just added a feature request to the MooseX::Getopt queue to allow such configuration: https://rt.cpan.org/Ticket/Display.html?id=58704 (so if you like it, please reply with a "me too") :)
Ether