2

I got this code below to work as I need, but would like to know if there's a better way of doing this without quotes.

myScript.pl --filter 'key1 foo bar' --filter 'key2 baz qux'

#!/usr/local/bin/perl5.8.8
use warnings;
use strict;
use Getopt::Long;
use Data::Dumper;

my %filter;

GetOptions("filter=s" => sub { my @args = split(/\s/, $_[1]); $filter{$args[0]}{value1} = $args[1]; $filter{$args[0]}{value2} = $args[2]; });

print Dumper %filter;

I get a satisfactory output:

$VAR1 = 'key2';
$VAR2 = {
          'value1' => 'baz',
          'value2' => 'qux'
        };
$VAR3 = 'key1';
$VAR4 = {
          'value1' => 'foo',
          'value2' => 'bar'
        };

However, I would like to use it like this, without quotes:

myScript.pl --filter key1 foo bar --filter key2 baz qux --other_option ...

key1 and key2 are hash keys here and will be unique.

Any ideas/suggestions?

Wilderness
  • 1,309
  • 2
  • 15
  • 27

2 Answers2

4

When I last checked (a couple of years ago), none of the 20-30 Getopt modules listed on CPAN would handle a string of arguments as you show, and most of the C-based argument parsing code I know of does not handle that either. (I do have a C code parser that handles it, provided you know how many arguments to consume. It is not clear whether you require 1 key and 2 values or whether the list of values can be more variable than that.)


Maybe I didn't look carefully enough.

Getopt::Long has the option:

Warning: What follows is an experimental feature.

Options can take multiple values at once, for example

--coordinates 52.2 16.4 --rgbcolor 255 255 149

This can be accomplished by adding a repeat specifier to the option specification. Repeat specifiers are very similar to the {...} repeat specifiers that can be used with regular expression patterns. For example, the above command line would be handled as follows:

GetOptions('coordinates=f{2}' => \@coor, 'rgbcolor=i{3}' => \@color);

The destination for the option must be an array or array reference.

It is also possible to specify the minimal and maximal number of arguments an option takes. foo=s{2,4} indicates an option that takes at least two and at most 4 arguments. foo=s{,} indicates one or more values; foo:s{,} indicates zero or more option values.

This would generate an array with the key and two values in it. Given that this needs to be combined with the ability to have multiple entries (one per --filter), you may still be out of luck, but you should explore Getopt::Long excruciatingly carefully.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Thanks ! The number of arguments will remain constant. 1 key and 2 values. – Wilderness Nov 26 '11 at 06:29
  • Yeah. I read it but didn't find any more clues which would help me solve this problem. I used the same example above with --filter1, --filter2, etc., just as you suggested. Never mind. I will use it as is. Thanks for the suggestions. – Wilderness Nov 26 '11 at 06:59
3

You may specify a callback for non-option arguments using the option name <> and adjust your %filters hash appropriately, like this :

GetOptions('filter=s' =>  \&set_filter, '<>' => \&non_option);

I'd imagine your @ARGV would end up empty unless you use a -- though.

Jeff Burdges
  • 4,204
  • 23
  • 46
  • Thanks ! I tried this and it worked. I found it [here](http://search.cpan.org/dist/Getopt-Long/lib/Getopt/Long.pm#Argument_callback). – Wilderness Nov 26 '11 at 07:04