Jay
Jay

Reputation: 469

How to get options in the order entered by the user, using Perl's Getopt::Long?

I have an existing Perl program that uses Getopt package and Getopt::Long::Configure with permute as one of the options. However, now I need to keep the order of the options entered by the user. There is an option $RETURN_IN_ORDER mentioned in the Long.pm, however doesn't seem to be used anywhere at all.

When I pass return_in_order, I am getting the following error.


Getopt::Long: unknown config parameter "return_in_order" at C:/Program Files/IBM/RationalSDLC/common/lib/perl5/5.8.6/Getopt/Long.pm line 1199.


Can someone please tell me if this is supported at all and if so, the right way to use? If not, I would like to know the other alternatives I have.

Thanks.

Upvotes: 3

Views: 2195

Answers (7)

cxw
cxw

Reputation: 17041

Very late to the party. I did this using an option-handling subroutine. My particular use case is that I need to handle any number of -e <foo> and -f <foo> options in any order, preserving that order (for a personal project).

use Data::Dumper; use Getopt::Long; use strict; use warnings;
my @Sources;    # Each element is [was -f, parameter]

my $dr_save_source = sub {      # Called each time we see -e or -f
    my ($which, $text) = @_;
    push @Sources, [$which eq "f", $text];
}; # dr_save_source

GetOptions("e=s@" => $dr_save_source, "f=s@" => $dr_save_source);
print Dumper(\@Sources);

Providing the subroutine reference $dr_save_source as the value associated with an option specification (=> $dr_save_source) tells GetOptions to call that subroutine to handle the option whenever it shows up.

This might get a bit clumsy as the number of options increased, but it is ... an option.

Upvotes: 0

Alex Aminoff
Alex Aminoff

Reputation: 11

Needing to know the order in which options were specified is why I still use Getopt::Mixed. That module has a nextOption function which you can loop over, and it will give you the options in the order they were on the command line.

My use case for this is include and exclude regexps:

myscript /usr --include /usr/local/bin --exclude /usr/local

What actually happens of course also depends on how I handle the includes and excludes inside by script, but I need to know the order.

Upvotes: 1

Jay
Jay

Reputation: 469

The requirement in my case is very different as the command line parameters are going to be a combination of options and arguments, such as the following.

mytool -arg1 value 1 -arg2 value2 -arg3 value3

And this is why require_order is not particularly helpful.

And as I just figured out, the problem is not really with the parsing component. It's with the hash object that is used to store them.

As tsee right pointed out, the order will be same if we use the default configurations.

Thanks folks, anyways.

Upvotes: 2

tsee
tsee

Reputation: 5072

Maybe it would have helped if you provided an example call to your program.

Getopt::Long supports mixing options with ordinary "positional" args:

./foo --option1 --option2 file1 file2 file3

If you only parse the options with GetOptions, file1 to 3 will be left in @ARGV in the order they appeared. Maybe you can use that behaviour to achieve what you want.

Furthermore, you can specify the same option multiple times and have the results put in an array (in order!):

#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
my @permute;
GetOptions(
  'p=s' => \@permute,
);

print "$_\n" for @permute;

"perl foo.pl -p=1 -p=2 -p=3 -p=4" results in this output: (Note: "-p X" works the same as "-p=X")

1
2
3
4

Upvotes: 2

Jonathan Leffler
Jonathan Leffler

Reputation: 754010

You have two answers pointing at 'require_order', but I think both those answers are misunderstanding both what 'require_order' does and what you seek.

If 'require_order' is unset, then you can write (on the command line):

-a file -b

Where both -a and -b are simple options (not taking an argument). With 'require_order' set, the presence of 'file' terminates the options and the '-b' flag becomes a 'file name'.

What I think you are seeking is a mechanism that allows you to tell that '-a' appeared before both 'file' and '-b'. I do not think that Getopt::Long supports that. In fact, I'm not aware of any Getopt::* module that does that (other than my own, unpublished, Getopt::JLSS which I sometimes use). [If you are interested in the code, send me an email at Gmail, using a dot between first and last name.]

Upvotes: 6

SquareCog
SquareCog

Reputation: 19666

I think you want "require_order"

http://perldoc.perl.org/Getopt/Long.html#Configuring-Getopt%3a%3aLong

Upvotes: 6

C. K. Young
C. K. Young

Reputation: 223043

It's called require_order, according to the manpage I have here. :-)

Upvotes: 5

Related Questions