patternMinor
Parsing command line arguments in Perl
Viewed 0 times
argumentslineperlparsingcommand
Problem
I use this idiom to parse command line arguments in Perl:
This let's me do things like:
Here's a short example script using this idiom:
Is this a good technique for parsing command line arguments in Perl?
Is there a better way?
I'm also interested in improvement ideas about the short script itself too.
my @args;
my $encode = 1;
while (@ARGV) {
for (shift(@ARGV)) {
($_ eq '-h' || $_ eq '--help') && do { &usage(); };
# ... more options here
($_ eq '--') && do { push(@args, @ARGV); undef @ARGV; last; };
($_ =~ m/^-.+/) && do { print "Unknown option: $_\n"; &usage(); };
push(@args, $_);
}
}This let's me do things like:
- Supports command line arguments in arbitrary order
- Supports using
--to use any following arguments "as is", without parsing
- Stop parsing and print usage message on
-h, or--help
- Raise error if a
-somethingflag is detected that is not matched by any of the parsing rules
Here's a short example script using this idiom:
#!/usr/bin/env perl
use strict;
use warnings;
&usage() unless @ARGV;
my @args;
my $encode = 1;
while (@ARGV) {
for (shift(@ARGV)) {
($_ eq '-h' || $_ eq '--help') && do { &usage(); };
($_ eq '-D' || $_ eq '--decode') && do { $encode = ! $encode; last; };
($_ eq '--') && do { push(@args, @ARGV); undef @ARGV; last; };
($_ =~ m/^-.+/) && do { print "Unknown option: $_\n"; &usage(); };
push(@args, $_);
}
}
sub usage {
$0 =~ m|[^/]+$|;
print "Usage: %%CODEBLOCK_1%%amp; [-h|--help] [-D|--decode]\n";
print "\n";
print "Encode (= default) or decode Base64\n";
exit 1;
}
use MIME::Base64;
if ($encode) {
print map(&MIME::Base64::encode_base64($_), @args);
} else {
print map(&MIME::Base64::decode_base64($_), @args);
}Is this a good technique for parsing command line arguments in Perl?
Is there a better way?
I'm also interested in improvement ideas about the short script itself too.
Solution
There are several modules on CPAN that are made for this task. They all reside in the
If you are interested in something more fancy, you could have a look at
What I definitely would recommend is that you take a look at
Getopt namespace. Getopt::Long even comes with the standard distribution. So coming to your question: Yes, there are better ways. If you are interested in something more fancy, you could have a look at
Getopt::Declare where you can write the usage page and fill your variables in the same place. It has a downside, though since it introduces another DSL.What I definitely would recommend is that you take a look at
<<HERE docs for printing longer texts. Some people dislike them,because of their strange syntactic properties, but they are the usual way to express multiline strings in perl.Context
StackExchange Code Review Q#64753, answer score: 9
Revisions (0)
No revisions yet.