2

I'm trying to create a script/application which accepts command line arguments when run. Of course, this is a day-to-day thing, but seeing as this is the first time I'm doing it, I'm looking for some guidance. Let's say my script can take these kinds of command line arguments:

script -a -p /path/to/pipe -l mail.Error -m [email protected]
script -a -l mail.Error -m [email protected] -p /path/to/pipe

and so on....

Due to the flexible nature of command line scripts, the arguments you can pass to it can some in a variety of orders and could be missing/have invalid arguments. Now, I know this can be solved by being very strict about how the arguments must show up (first -a, then -p with a path, then -l with a log facility/priority and finally -m with a valid email) and by testing all possible occurrences of them.

But there has to be a better way. This is incredibly inefficient (to me) and I was wondering if there was a better way of doing things. I want to remain as flexible as possible and just make things work instead of focusing on strict usage.

3 Answers 3

6

I use Getopt::Long for arguments.

Untested example:

use Getopt::Long;
## set defaults
my $path   = '/tmp';
my $log = 'm.Error';
my $email = '[email protected]';
my $a = 0;
my $result = GetOptions ("path=s"  => \$path,
                         "log=s"   => \$log,
                         "a"       => \$a,
                         "email=s" => \$email);
## both script -a -p /path/to/pipe -l mail.Error -m [email protected]
## and script -a -l mail.Error -m [email protected] -p /path/to/pipe
## should work now
Sign up to request clarification or add additional context in comments.

1 Comment

You can also pass GetOptions a hash reference, and it will store all the information to the hash. For example, given GetOptions(\%opt, "path=s", "log=s") passing -path /tmp will give you $opt{path} == "/tmp". I find it convenient to have information from command-line options easily visible in the code.
2

Use Getopt::Std if you only want 1-character options, Getopt::Long if you want to support longer argument names.

2 Comments

Just always use Getopt::Long — it can handle both.
Yes, but Getopt::Std makes bundling a bit more straightforward, for example treating -abc as -a -b -c (at the expense of not handing long options at all). Personally, I don't use bundling, and I haven't used Getopt::Std in years. For the gory details, perldoc Getopt::Long and read the "Bundling" section (there are several configuration options).
0

Getopt::Long can automatically parse your command line into a hash variable. The order on the command line does not matter. You can check if options are given or not by checking hash keys.

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

my %opts;
GetOptions(\%opts, qw(a p=s l=s m=s)) or die;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.