开发者

Perl: Is it possible to prevent options recognition stop after double dash (--) when using GetOpt?

I wish to write down in perl scripts that receive and option with values lists that ends with double dash (--). example:

% perl_script -letters a b c -- -words he she we --

as result of running this command line, two arrays will be created: letters = [a b c ]; words = [he she we];

Using GetOption does not support this, b.c after using double dash , the optio开发者_Python百科ns recognitions stops.


Do you have some specific reason to use such a confusing delimiter? -- has a known meaning to most script users and this is not it.

If you need to read in options with lists, Getopt::Long has methods to deal with input arrays, perhaps something like this could help you; look under "Options with multiple values". This module is in the standard distribution, so you don't even have to install anything. I use it for any script that needs more than one (maybe two) inputs and definitely if any inputs are optional.

See also here and even more here.

Here is a quick example, if you have the flexibility to change your input syntax, this gets you the functionality you are requesting:

#!/usr/bin/env perl
# file: test.pl

use strict;
use warnings;

use Getopt::Long;

my @letters;
my @words;

GetOptions(
  "letters=s{,}" => \@letters,
  "words=s{,}" => \@words
);

print "Letters: " . join(", ", @letters) . "\n";
print "Words: " . join(", ", @words) . "\n";

Gives:

$ ./test.pl --letters a b c --words he she we
Letters: a, b, c
Words: he, she, we

While I would never encourage writing one's own parser, I could not understand why someone would choose the form you had, so I am going to operate under the assumption that you are not in control of this format and need to work around it. If this is the case (otherwise, please consider a more standard syntax and use the example above), here is a simple parser that should get you started.

N.B. the reason NOT to write your own is others are well tested and have fringe cases ironed out. Also do you know what you would do with something between a -- and a -title? I assumed that since a new -title would end the previous one, that you might have something between and have lumped all these in order in a 'default' key.

#!/usr/bin/env perl
# file: test_as_asked.pl
# @ARGV = qw/default1 -letters a b c -- default2 -words he she we -- default3/;

use strict;
use warnings;

my %opts;
# catch options before a -title (into group called default)
my $current_group = 'default';
foreach my $opt (@ARGV) {
  if ($opt =~ /\-\-/) {
    # catch options between a -- and next -title
    $current_group = 'default';
  } elsif ($opt =~ /\-(.*)/) {
    $current_group = $1;
  } else {
    push @{ $opts{$current_group} }, $opt;
  }
}

foreach my $key (keys %opts) {
  print "$key => " . join(", ", @{ $opts{$key} }) . "\n";
}

Gives:

$ ./test_as_asked.pl default1 -letters a b c -- default2 -words he she we -- default3
letters => a, b, c
default => default1, default2, default3
words => he, she, we


How about

-letters "a b c" -words "he she we" 

?


You can handle your arguments in multiple passes if you want. Look at the pass_through option. This is what I do in ack because some options affect other options, so I have to handle the --type options first, and then handle out the rest.


It's bad practice to disable the dash dash backdoor.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜