Getopt::Long − この便利だが悩ましいモジュール
Getopt::Longという便利なモジュールがある。
コマンドラインにおけるperl myscript.pl --input input.txt --output output.txt
みたいなパラメータの処理を宜しくやってくれるモジュールである。こいつを組み込んだだけで、なにか自作スクリプトのグレードが2段階ぐらい上がったような錯覚を覚える。俺はそういう錯覚が大好きである。したがって俺はこのモジュールの機能のことはとても気に入っている。
しかしその反面、俺はこのモジュールに非常に大きな不満を抱いている。
それは、大文字と小文字がごちゃごちゃ混在していることと、単数形と複数形がごちゃごちゃ混在していることだ。
もうね、スクリプトを組むたびに、あれ、getopt::Longだっけ? Getopts::Longだっけ? getOpt::Longだっけ? と悩むわけですよ。
その状況を10年以上も続けて、どうやら俺は大文字と小文字の使い分けが超絶苦手であるとの事実を受け入れざるを得まいと悟ったわけだ1。
正しいスペルが覚えきれないし、さらにいえば俺はシフトキーと言うやつが大嫌いだ。getOpぐらいのところで指がつりそうになる。
もう全部小文字にしてくれ。あと単数形一択に変えてくれ。…と本家に頼み込んでも受け入れてはくれまいから、自分用のwrapperを作って解決することにした。
名付けてarg.pm
以下に示すコードをarg.pm
として適切なディレクトリ2に放り込むと、スクリプト中でuse arg;
できるようになる。
そう。use Getopt::Long;
という長ったらしいコードを打つ代わりに、use arg;
で事足りるのである。素晴らしい!
さらに、GetOptions(...
の代わりにargv(...
またはarg(...
である。大文字フリー! シンプル! 快適!
use strict;
use warnings;
use Getopt::Long;
use Data::Dumper;
sub argv{
my(%x)=@_;
my %opt; my @dl;
foreach my $key (sort keys %x){
my($key1, $desc) = $key=~/(\S+)?(?:\s*(.*))?/;
my($k,$k2,$t) = $key1=~/(([^=]+)(?:=(\S+))?)/;
$opt{$key1} = $x{$key};
($t) or $t = "s";
my $t2 = ($t eq 's')?'string'
:($t eq 'i')?'integer'
:($t eq 'f')?'floating point value':'';
push(@dl, "--$k2:\ttype=$t2. $desc");
}
(defined $dl[0]) and (not defined $opt{help}) and $opt{help}=sub {print join("\n", @dl), "\n"; exit()};
GetOptions(%opt);
}
*arg = *argv;
1;
使い方は簡単
Getoptions()のラッパーなので、基本的にこの関数の使い方に準拠する形でarg()を使うことになる。
arg(
"input=s" => \$input,
"output=s" => \$output
);
簡易ヘルプ機能も追加
ここまでで済ませても良かったのだが、なにかプログラムを作ると機能拡張しないと気が済まない性格でして。コマンドラインオプションの使い方を簡易にユーザに知らしめる「ヘルプ機能」をつけてしまった。具体的には次のように使う。
arg(
"input=s Input file name" => \$input,
"output=s Output file name" => \$output
);
このように、Getopt::Long互換なパラメータ文字列の後ろに、スペースを挟んで当該オプションの説明を書くのだ。すると、arg()内の細工により、--help
オプションが自動的に追加される(ただし、すでに明示的にhelpオプションが設定されている場合、この処理は抑止される)。
こんな感じで使える。
perl ~/work/testarg.pl --help
--input: type=string. Input file name
--output: type=string. Output file name
perldocを使うのが正道であるが、あれはちょっと大げさだからね。コマンドラインオプションの説明が一切示されないのも困るが、かといっていちいちperldocの独特の文法と格闘したくもない、という状況は少なくないと思う。そういうときにこの機能は便利であろうと考えている。